Încărcarea cu șine și agrafă

Acesta este ultimul articol din seria "Încărcarea cu șine". În ultimele două luni am discutat deja pietrele Altarului, Dragonfly și Carrierwave. Vizitatorul de astăzi este Paperclip de Thoughtbot, o companie care administrează pietre precum FactoryGirl și Bourbon.

Paperclip este probabil cea mai populară soluție de administrare a atașamentelor pentru Rails (mai mult de 13 milioane de descărcări) și pentru un motiv bun: are o mulțime de caracteristici, o comunitate excelentă și o documentație amănunțită. Deci, sperăm că sunteți dornici să aflați mai multe despre această bijuterie!

În acest articol veți învăța cum să:

  • Pregătiți-vă pentru instalarea Paperclip
  • Integrați agrafa într-o aplicație Rails
  • Adăugați validări de atașament
  • Generați miniaturi și procesați imagini
  • Obstrucționați adresele URL
  • Stocați atașamente pe Amazon S3
  • Secure fișiere în cloud prin introducerea logicii de autorizare

Codul sursă pentru acest articol este disponibil pe GitHub.

preparate

Înainte de a ne arunca cu capul în cod, să discutăm în primul rând despre unele avertismente pe care trebuie să le cunoașteți pentru a lucra cu Paperclip:

  • Cea mai recentă versiune a Paperclip suportă Rails 4.2+ și Ruby 2.1+. Această bijuterie poate fi de asemenea utilizată fără șine.
  • ImageMagick trebuie să fie instalat pe PC (este disponibil pentru toate platformele majore) și Paperclip ar trebui să aibă acces la el.
  • fişier comanda ar trebui să fie disponibilă din linia de comandă. Pentru Windows este disponibil prin Development Kit, deci urmați aceste instrucțiuni dacă nu aveți încă instalat DevKit.

Când sunteți gata, continuați și creați o nouă aplicație Rails (voi folosi Rails 5.0.2) fără suita de testare implicită:

șine noi UploadingWithPaperclip -T

Integrarea agrafă de birou

Puneți în bijuterie din cartelă:

Gemfile

gem "agrafă", "~> 5,1"

Instalați-l:

instalare pachet

Să presupunem că creăm o aplicație pentru rafturi care prezintă o listă de cărți. Fiecare carte va avea un titlu, o descriere, un nume de autor și o imagine de copertă. Pentru a începe, generați și aplicați următoarea migrare:

rails g model Titlu carte: descriere șir: text imagine: atașament autor: string șir db: migrate

Rețineți atașament tip care este prezentat pentru noi de Paperclip. Sub capota, se vor crea patru câmpuri pentru noi:

  • image_file_name
  • IMAGE_FILE_SIZE
  • image_content_type
  • image_updated_at

Spre deosebire de pietrele Shrine și Carrierwave, Paperclip nu are un fișier separat cu configurații. Toate setările sunt definite în interiorul modelului însuși folosind has_attached_file metoda, adăugați-o acum:

modele / book.rb

has_attached_file: imagine

Înainte de a trece la partea principală, să creați un controler împreună cu unele vederi și rute.

Crearea controlerului, a vizualizărilor și a rutelor

Controlorul nostru va fi foarte simplu:

books_controller.rb

clasa BooksController < ApplicationController before_action :set_book, only: [:show, :download] def index @books = Book.order('created_at DESC') end def new @book = Book.new end def show end def create @book = Book.new(book_params) if @book.save redirect_to books_path else render :new end end private def book_params params.require(:book).permit(:title, :description, :image, :author) end def set_book @book = Book.find(params[:id]) end end

Aici este un index vizualizare și parțial:

vizualizari / carti / index.html.erb

Raft de cărți

<%= link_to 'Add book', new_book_path %>
    <%= render @books %>

vizualizari / carti / _book.html.erb

  • <%= link_to book.title, book_path(book) %> de <%= book.author %>
  • Acum rutele:

    config / routes.rb

    Rails.application.routes.draw face resurse: cărți rădăcină la: "cărți # index" sfârșitul 

    Frumos! Acum, să mergem la secțiunea principală și să codificăm nou acțiune și o formă.

    Încărcarea fișierelor

    În general, încărcarea cu Paperclip este ușoară. Trebuie doar să permiteți atributul corespunzător (în cazul nostru este vorba de imagine atribut și l-am permis deja) și să prezinte un câmp de fișier în formularul dvs. S-o facem acum:

    vizualizari / carti / new.html.erb

    Adăugați o carte

    <%= render 'form', book: @book %>

    vizualizari / carti / _form.html.erb

    <%= form_for book do |f| %> 
    <%= f.label :title %> <%= f.text_field :title %>
    <%= f.label :author %> <%= f.text_field :author %>
    <%= f.label :description %> <%= f.text_area :description %>
    <%= f.label :image %> <%= f.file_field :image %>
    <%= f.submit %> <% end %>

    Cu această configurație, puteți începe deja să efectuați încărcări, dar este bine să introduceți și unele validări.

    Adăugarea de validări

    Validările din Paperclip pot fi scrise cu ajutorul unor agenți vechi cum ar fi validates_attachment_presence și validates_attachment_content_type sau prin angajarea validates_attachment metoda de definire a mai multor reguli simultan. Să rămânem cu cea de-a doua opțiune:

    modele / book.rb

     validates_attachment: image, content_type: content_type: /\Aimage\/.*\z/, dimensiune: less_than: 1.megabyte

    Codul este foarte simplu, după cum puteți vedea. Solicităm ca fișierul să fie o imagine mai mică de 1 megabyte. Rețineți că în cazul în care validarea nu reușește, nu se va efectua nicio postprocesare. Paperclip are deja unele mesaje de eroare setate pentru limba engleză, dar dacă doriți să acceptați alte limbi, includeți bijuteria paperclip-i18n în Gemfile.

    Un alt lucru important este de menționat că Paperclip vă cere să validați tipul de conținut sau numele fișierului pentru toate atașamentele, altfel va crește o eroare. Dacă sunteți 100% sigur că nu aveți nevoie de astfel de validări (care este un caz rar), utilizați do_not_validate_attachment_file_type pentru a spune în mod explicit câmpurile care nu trebuie verificate.

    După adăugarea validărilor, să afișăm, de asemenea, mesaje de eroare în formularul nostru:

    vizualizari / partajate / _errors.html.erb

    <% if object.errors.any? %> 

    Au fost găsite unele erori:

      <% object.errors.full_messages.each do |message| %>
    • <%= message %>
    • <% end %>
    <% end %>

    vizualizari / carti / _form.html.erb

    <%= render 'shared/errors', object: book %>

    Afișarea imaginilor

    Bine, deci imaginile încărcate ar trebui afișate cumva. Acest lucru se face folosind IMAGE_TAG helper și a URL-ul metodă. Creeaza o spectacol vedere:

    vizualizari / carti / show.html.erb

    <%= @book.title %> de <%= @book.author %>

    <%= image_tag(@book.image.url) if @book.image.exists? %>

    <%= @book.description %>

    Afișăm o imagine numai dacă există cu adevărat pe unitate. În plus, dacă utilizați spațiu de stocare în cloud, Paperclip va efectua o solicitare de rețea și va verifica existența fișierului. Desigur, această operațiune poate dura ceva timp, deci puteți utiliza prezent? sau fişier? metode în schimb: ei vor pur și simplu să se asigure că image_file_name câmpul este populat cu un anumit conținut.

    UFI Obfuscation

    Implicit, toate atașările sunt stocate în interiorul / Sistemul public , astfel încât probabil veți dori să o excludeți din sistemul de control al versiunilor: 

    .gitignore

    / Sistemul public

    Cu toate acestea, este posibil ca afișarea unui fișier URI complet în fișier să nu fie întotdeauna o idee bună și este posibil să trebuiască să o înșelați cumva. Cea mai ușoară modalitate de a permite obfuscarea este prin furnizarea a doi parametri către metoda has_attached_file:

    modele / book.rb

    url: "/system/:hash.:extension", hash_secret: "longSecretString"

    Valorile corespunzătoare vor fi interpolate în URL-ul automat. hash_secret este un câmp obligatoriu și cel mai simplu mod de generare a acestuia este utilizarea:

    șinele secrete

    Lucrul cu stiluri

    În multe cazuri, este preferabil să afișați o miniatură a imaginii cu o lățime și înălțime predefinită pentru a salva lățimea de bandă. Paperclip rezolvă această problemă prin utilizarea stilurilor: fiecare stil are un nume și un set de reguli, cum ar fi dimensiunile, formatul, calitatea etc..

    Să presupunem că vrem ca imaginea originală și miniatură să fie convertite în format JPEG. Miniatură ar trebui tăiată la 300x300px:

    modele / book.rb

     has_attached_file: imagine, stiluri: thumb: ["300x300 #",: jpeg], original: [: jpeg]

    # este o setare de geometrie care înseamnă: "Decupați dacă este necesar păstrând în același timp raportul de aspect".

    De asemenea, putem oferi opțiuni suplimentare de conversie pentru fiecare stil. De exemplu, să oferim 70% calitate pentru degetele mari, în timp ce eliminăm toate metadatele și 90% calitate pentru imaginea originală pentru ao face puțin mai mică:

    modele / book.rb

     has_attached_file: imagine, stiluri: thumb: ["300x300 #",: jpeg], original: [: jpeg], convert_options: thumb: "-quality 70 -strip", original: "-quality 90"

    Frumos! Afișați miniaturile și furnizați link-ul către imaginea originală:

    vizualizari / carti / show.html.erb

    <%= link_to(image_tag(@book.image.url(:thumb)), @book.image.url, target: '_blank') if @book.image.exists? %> 

    Rețineți că, spre deosebire de Carrierwave, de exemplu, Paperclip nu vă permite să scrieți @ book.image.thumb.url.

    Dacă, din anumite motive, doriți să actualizați manual imaginile încărcate, puteți utiliza următoarele comenzi pentru a reîmprospăta numai miniaturile, a adăuga stiluri lipsă sau pentru a reîmprospăta toate imaginile:

    • rake paperclip: reîmprospătare: miniaturi CLASS = Rezervați
    • rake paperclip: refresh: missing_styles CLASS = Rezervați
    • rake colier: reîmprospătează CLASS = Rezervați

    Stocarea fișierelor în Cloud

    Ca toate soluțiile similare, Paperclip vă permite să încărcați fișiere în cloud. Din cutie, are suport pentru adaptoarele S3 și Fog, dar există și pietre pentru terțe părți pentru Azure și Dropbox. În această secțiune, vă voi arăta cum să integrați Paperclip cu Amazon S3. Mai întâi, aruncați bijuteria aws-sdk:

    gem 'aws-sdk'

    Instalați-l:

    instalare pachet

    Apoi, furnizați un nou set de opțiuni la has_attached_file metodă:

    modele / book.rb

     has_attached_file: imagine, stiluri: thumb: ["300x300 #",: jpeg], original: [: jpeg], convert_options: thumb: "-quality 70 -strip" :: s3, s3_credentials: acces_key_id: ENV ["S3_KEY"], secret_access_key: ENV ["S3_SECRET"], cupă: ENV ["S3_BUCKET"], s3_region: ENV ["S3_REGION"]

    Aici stau la gheața dotenv-șine pentru a stabili variabilele de mediu. Puteți furniza toate valorile direct în interiorul modelului, dar nu îl faceți public.

    Ce e interesant este asta s3_credentials acceptă, de asemenea, o cale către un fișier YAML care conține cheile și numele unei găleți. În plus, puteți seta diferite valori pentru medii diferite, cum ar fi: 

    dezvoltare: acces_key_id: key1 secret_access_key: secret1 producție: access_key_id: key2 secret_access_key: secret2

    Asta e! Toate fișierele pe care le încărcați vor fi acum amplasate în galeria dvs. S3.

    Securizarea fișierelor în cloud

    Să presupunem că nu doriți ca fișierele încărcate să fie disponibile pentru toată lumea. În mod prestabilit, toate încărcările în cloud sunt marcate ca fiind publice, ceea ce înseamnă că oricine poate deschide fișierul prin linkul direct. Dacă doriți să introduceți o logică de autorizare și să verificați cine poate vizualiza fișierul, setați-l s3_permissions opțiunea pentru :privat asa:

     has_attached_file: imagine, stiluri: thumb: ["300x300 #",: jpeg], original: [: jpeg], convert_options: thumb: "-quality 70 -strip" :: s3, s3_credentials: acces_key_id: ENV ["S3_KEY"], secret_access_key: ENV ["S3_SECRET"], cupă: ENV ["S3_BUCKET"], s3_region: ENV [S3_REGION]

    Acum, cu toate acestea, nimeni, cu excepția dvs., va putea să vadă fișierele. Prin urmare, să creăm un nou Descarca acțiune pentru BooksController:

    books_controller.rb

     def descărcați redirect_to @ book.image.expiring_url end

    Această acțiune va redirecționa pur și simplu utilizatorii către imagine printr-un link care expiră. Folosind această abordare, puteți introduce acum orice logică de autorizare utilizând pietre precum CanCanCan sau Pundit.

    Nu uitați să setați traseul membru:

    config / routes.rb

     resurse: cărțile fac membrii nu se termină "descărcare"

    Ajutorul trebuie folosit în felul următor:

    link_to ('Vizualizare imagine', download_book_path (@book), țintă: '_blank')

    Concluzie

    Am ajuns la sfârșitul acestui articol! Astăzi am văzut Paperclip, o soluție de gestionare a atașamentelor pentru Rails, în acțiune și am discutat despre principalele sale concepte. Există mult mai mult pentru această bijuterie, deci asigurați-vă că vedeți documentația sa.

    De asemenea, vă recomand să vizitați pagina wiki Paperclip deoarece prezintă o listă de tutoriale "cum să" și o grămadă de link-uri către pietre de la terți care susțin Azure și Cloudinary și vă permit să micșorați cu ușurință fișierele încărcate.

    Vă mulțumim că ați rămas cu mine și vă voi vedea în curând!

    Cod