Questo è l'ultimo articolo nella serie "Caricamento con rotaie". Negli ultimi due mesi abbiamo già discusso le gemme Shrine, Dragonfly e Carrierwave. L'ospite di oggi è Paperclip di Thoughtbot, una società che gestisce gemme come FactoryGirl e Bourbon.
Paperclip è probabilmente la soluzione di gestione degli allegati più popolare per Rails (oltre 13 milioni di download), e per una buona ragione: ha molte funzionalità, una grande community e una documentazione completa. Quindi spero che tu sia desideroso di saperne di più su questa gemma!
In questo articolo imparerai come:
Il codice sorgente per questo articolo è disponibile su GitHub.
Prima di immergerci nel codice, esaminiamo innanzitutto alcune avvertenze che è necessario conoscere per poter lavorare con successo con Paperclip:
file
il comando dovrebbe essere disponibile dalla riga di comando. Per Windows è disponibile tramite il kit di sviluppo, quindi segui queste istruzioni se non hai ancora installato DevKit.Quando sei pronto, vai avanti e crea una nuova applicazione Rails (userò Rails 5.0.2) senza la suite di test predefinita:
rota nuovo UploadingWithPaperclip -T
Lascia cadere la gemma Paperclip:
gem "paperclip", "~> 5.1"
Installalo:
installazione bundle
Supponiamo di creare un'applicazione per scaffali che presenti un elenco di libri. Ogni libro avrà un titolo, una descrizione, il nome dell'autore e un'immagine di copertina. Per iniziare, genera e applica la seguente migrazione:
rails g model Titolo del libro: descrizione stringa: testo immagine: allegato autore: string rails db: migrate
Notare la attaccamento
tipo che ci viene presentato da Paperclip. Sotto il cofano, creeremo quattro campi per noi:
image_file_name
IMAGE_FILE_SIZE
image_content_type
image_updated_at
In contrasto con le gemme Shrine e Carrierwave, Paperclip non ha un file separato con configurazioni. Tutte le impostazioni sono definite all'interno del modello stesso utilizzando has_attached_file
metodo, quindi aggiungilo ora:
has_attached_file: image
Prima di procedere alla parte principale, creiamo anche un controller con alcune viste e percorsi.
Il nostro controller sarà molto semplice:
classe 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
Ecco un indice vista e parziale:
Bookshelf
<%= link_to 'Add book', new_book_path %>
Ora i percorsi:
Rails.application.routes.draw fa risorse: i libri sono rootati a: 'books # index' end
Bello! Ora passiamo alla sezione principale e digitiamo il codice nuovo azione e una forma.
Tutto sommato, fare caricamenti con Paperclip è facile. Devi solo permettere l'attributo corrispondente (nel nostro caso quello è il Immagine
attributo, e lo abbiamo già autorizzato) e presentare un campo file nel modulo. Facciamolo adesso:
Aggiungi un libro
<%= render 'form', book: @book %>
<%= 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 %>
Con questa configurazione, puoi già iniziare a eseguire caricamenti, ma è consigliabile introdurre anche alcune convalide.
Le convalide in Paperclip possono essere scritte usando vecchi aiutanti come validates_attachment_presence
e validates_attachment_content_type
o impiegando il validates_attachment
metodo per definire più regole contemporaneamente. Rimaniamo con quest'ultima opzione:
validates_attachment: image, content_type: content_type: /\Aimage\/.*\z/, size: less_than: 1.megabyte
Il codice è davvero semplice, come puoi vedere. Richiediamo che il file sia un'immagine di dimensioni inferiori a 1 megabyte. Si noti che se la convalida fallisce, non verrà eseguita alcuna post-elaborazione. Paperclip ha già alcuni messaggi di errore impostati per la lingua inglese, ma se vuoi supportare altre lingue, includi la gemma paperclip-i18n nel tuo Gemfile.
Un'altra cosa importante da ricordare è che Paperclip richiede di convalidare il tipo di contenuto o il nome del file di tutti gli allegati, altrimenti genererà un errore. Se sei sicuro al 100% che non hai bisogno di tali convalide (che è un caso raro), usa do_not_validate_attachment_file_type
per dire esplicitamente quali campi non dovrebbero essere controllati.
Dopo aver aggiunto le convalide, mostriamo anche i messaggi di errore nel nostro modulo:
<% if object.errors.any? %>Alcuni errori sono stati trovati:
<%= render 'shared/errors', object: book %>
Ok, quindi ora le immagini caricate dovrebbero essere visualizzate in qualche modo. Questo viene fatto usando il image_tag
aiutante e a url
metodo. Creare un mostrare vista:
<%= @book.title %> di <%= @book.author %>
<%= image_tag(@book.image.url) if @book.image.exists? %><%= @book.description %>
Stiamo visualizzando un'immagine solo se esiste realmente sul disco. Inoltre, se si utilizza l'archiviazione cloud, Paperclip eseguirà una richiesta di rete e verificherà l'esistenza del file. Naturalmente, questa operazione potrebbe richiedere del tempo, quindi potresti usare il presente?
o file?
metodi invece: si accerteranno semplicemente che il image_file_name
il campo è popolato con alcuni contenuti.
Per impostazione predefinita, tutti gli allegati sono memorizzati all'interno di / Sistema pubblico cartella, quindi probabilmente vorrai escluderla dal sistema di controllo della versione:
/ Sistema pubblico
Tuttavia, la visualizzazione di un intero URI nel file potrebbe non essere sempre una buona idea e potrebbe essere necessario nasconderla in qualche modo. Il modo più semplice per abilitare l'offuscamento consiste nel fornire due parametri a metodo has_attached_file
:
url: "/system/:hash.:extension", hash_secret: "longSecretString"
I valori corretti saranno interpolati nel url
automaticamente. hash_secret
è un campo obbligatorio e il modo più semplice per generarlo è utilizzando:
rotaie segrete
In molti casi, è preferibile visualizzare la miniatura di un'immagine con larghezza e altezza predefinite per risparmiare larghezza di banda. Paperclip risolve questo usando gli stili: ogni stile ha un nome e un insieme di regole, come dimensioni, formato, qualità, ecc.
Supponiamo che vogliamo che l'immagine originale e la sua miniatura siano convertite in formato JPEG. La miniatura dovrebbe essere ritagliata a 300x300px:
has_attached_file: image, styles: thumb: ["300x300 #",: jpeg], originale: [: jpeg]
#
è un'impostazione della geometria che significa: "Ritaglia se necessario mantenendo le proporzioni".
Possiamo anche fornire opzioni di conversione aggiuntive per ogni stile. Ad esempio, forniamo il 70% di qualità per i pollici rimuovendo tutti i metadati e il 90% di qualità per l'immagine originale per renderla un po 'più piccola:
has_attached_file: image, styles: thumb: ["300x300 #",: jpeg], originale: [: jpeg], convert_options: thumb: "-quality 70 -strip", originale: "-quality 90"
Bello! Visualizzare la miniatura e fornire il collegamento all'immagine originale:
<%= link_to(image_tag(@book.image.url(:thumb)), @book.image.url, target: '_blank') if @book.image.exists? %>
Nota che a differenza di Carrierwave, ad esempio, Paperclip non ti consente di scrivere @ book.image.thumb.url
.
Se, per qualche motivo, desideri aggiornare manualmente le immagini caricate, puoi utilizzare i seguenti comandi per aggiornare solo le anteprime, aggiungere gli stili mancanti o aggiornare tutte le immagini:
rake paperclip: refresh: thumbnails CLASS = Book
rake paperclip: refresh: missing_styles CLASS = Book
rake paperclip: refresh CLASS = Book
Come tutte le soluzioni simili, Paperclip ti consente di caricare file nel cloud. Fuori dalla scatola, ha il supporto per gli adattatori S3 e Fog, ma ci sono anche gemme di terze parti per Azure e Dropbox. In questa sezione, ti mostrerò come integrare Paperclip con Amazon S3. Innanzitutto, inserisci la gemma aws-sdk:
gemma 'aws-sdk'
Installalo:
installazione bundle
Quindi, fornire un nuovo set di opzioni al has_attached_file
metodo:
has_attached_file: image, styles: thumb: ["300x300 #",: jpeg], originale: [: jpeg], convert_options: thumb: "-quality 70 -strip", originale: "-quality 90", memoria :: s3, s3_credentials: access_key_id: ENV ["S3_KEY"], secret_access_key: ENV ["S3_SECRET"], bucket: ENV ["S3_BUCKET"], s3_region: ENV ["S3_REGION"]
Qui mi attengo alla gemma dotenv-rails per impostare le variabili d'ambiente. È possibile fornire tutti i valori direttamente all'interno del modello, ma non renderlo pubblicamente disponibile.
Quello che è interessante è quello s3_credentials
accetta anche un percorso per un file YAML contenente le chiavi e un nome bucket. Inoltre, puoi impostare valori diversi per ambienti diversi come questo:
sviluppo: access_key_id: key1 secret_access_key: secret1 produzione: access_key_id: key2 secret_access_key: secret2
Questo è tutto! Tutti i file che carichi verranno ora posizionati nel tuo bucket S3.
Supponiamo che tu non voglia che i tuoi file caricati siano disponibili per tutti. Per impostazione predefinita, tutti gli upload nel cloud sono contrassegnati come pubblici, il che significa che chiunque può aprire il file tramite il collegamento diretto. Se si desidera introdurre una logica di autorizzazione e verificare chi è in grado di visualizzare il file, impostare il s3_permissions
opzione a :privato
come questo:
has_attached_file: image, styles: thumb: ["300x300 #",: jpeg], originale: [: jpeg], convert_options: thumb: "-quality 70 -strip", originale: "-quality 90", memoria :: s3, s3_credentials: access_key_id: ENV ["S3_KEY"], secret_access_key: ENV ["S3_SECRET"], bucket: ENV ["S3_BUCKET"], s3_region: ENV ["S3_REGION"], s3_permissions:: private
Ora, tuttavia, nessuno tranne te sarà in grado di vedere i file. Pertanto, creiamo un nuovo Scaricare
azione per il BooksController
:
def scarica redirect_to @ book.image.expiring_url end
Questa azione semplicemente reindirizzerà gli utenti all'immagine tramite un link in scadenza. Utilizzando questo approccio, è ora possibile introdurre qualsiasi logica di autorizzazione utilizzando gemme come CanCanCan o Pundit.
Non dimenticare di impostare la rotta del membro:
risorse: i membri del libro ottengono il termine "download"
L'helper dovrebbe essere usato in questo modo:
link_to ('Visualizza immagine', download_book_path (@book), target: '_blank')
Siamo arrivati alla fine di questo articolo! Oggi abbiamo visto in azione Paperclip, una soluzione di gestione degli allegati per Rails, che ne ha discusso i concetti principali. C'è molto di più in questa gemma, quindi assicurati di vedere la sua documentazione.
Inoltre, ti consiglio di visitare la pagina wiki di Paperclip in quanto presenta un elenco di esercitazioni "how to" e una serie di collegamenti a gemme di terze parti che supportano Azure e Cloudinary e che ti consentono di minimizzare facilmente i file caricati.
Grazie per essere stato con me, e a presto!