Laster opp med Rails og Paperclip

Dette er den siste artikkelen i serien "Opplasting med skinner". I de siste par månedene har vi allerede diskutert Shrine, Dragonfly og Carrierwave gems. Dagens gjest er Paperclip by Thoughtbot, et selskap som forvalter edelstener som FactoryGirl og Bourbon.

Paperclip er trolig den mest populære vedleggsløsningen for Rails (over 13 millioner nedlastinger), og med god grunn: den har mange funksjoner, et stort fellesskap og grundig dokumentasjon. Så forhåpentligvis er du ivrig etter å lære mer om denne perlen!

I denne artikkelen lærer du hvordan du:

  • Forbered deg på Paperclip-installasjon
  • Integrer Paperclip i et Rails-program
  • Legg til vedleggsvalideringer
  • Generer miniatyrbilder og behandle bilder
  • Forklare webadresser
  • Lagre vedlegg på Amazon S3
  • Sikre filer i skyen ved å introdusere autorisasjonslogikk

Kildekoden for denne artikkelen er tilgjengelig på GitHub.

Forberedelser

Før vi dykker inn i koden, la oss først diskutere noen advarsler som du trenger å vite om for å kunne jobbe med Paperclip:

  • Den nyeste versjonen av Paperclip støtter Rails 4.2+ og Ruby 2.1+. Denne perlen kan også brukes uten Rails.
  • ImageMagick må installeres på din PC (den er tilgjengelig for alle store plattformer), og Paperclip skal kunne få tilgang til det.
  • De fil kommandoen bør være tilgjengelig fra kommandolinjen. For Windows er den tilgjengelig via Development Kit, så følg disse instruksjonene hvis du ikke har DevKit installert ennå.

Når du er klar, fortsett og opprett et nytt Rails-program (jeg skal bruke Rails 5.0.2) uten standard testing suite:

Skinner nye UploadingWithPaperclip -T

Integrere Paperclip

Drop i Paperclip-perlen:

Gemfile

perle "paperclip", "~> 5.1"

Installer den:

bunt installasjon

Anta at vi lager en bokhylleapplikasjon som presenterer en liste over bøker. Hver bok vil ha en tittel, en beskrivelse, en forfatters navn og et deksjonsbilde. For å starte, generer og bruk følgende migrering:

skinner g modell Boktittel: strengbeskrivelse: tekstbilde: vedleggsforfatter: strengskinner db: migrere

Legg merke til feste type som presenteres for oss av Paperclip. Under hetten skal det skape fire felt for oss:

  • image_file_name
  • IMAGE_FILE_SIZE
  • image_content_type
  • image_updated_at

I motsetning til Shrine og Carrierwave gems, har Paperclip ikke en egen fil med konfigurasjoner. Alle innstillinger er definert inne i selve modellen ved hjelp av has_attached_file metode, så legg den til nå:

modeller / book.rb

has_attached_file: bilde

Før vi fortsetter til hoveddelen, la oss også opprette en kontroller sammen med noen visninger og ruter.

Opprette kontrolleren, visninger og ruter

Vår kontroller vil være veldig grunnleggende:

books_controller.rb

klasse 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

Her er en index vis og delvis:

visninger / bøker / index.html.erb

Bokhylle

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

visninger / bøker / _book.html.erb

  • <%= link_to book.title, book_path(book) %> av <%= book.author %>
  • Nå ruter:

    config / routes.rb

    Rails.application.routes.draw gjør ressurser: bøker rot til: 'bøker # indeks' slutt 

    Hyggelig! La oss nå gå videre til hoveddelen og kode på ny handling og et skjema.

    Laster opp filer

    Alt i alt er det enkelt å laste opp med Paperclip. Du trenger bare å tillate den tilsvarende attributtet (i vårt tilfelle er det bilde attributt, og vi har allerede tillatt det) og presentere et filfelt i skjemaet ditt. La oss gjøre det nå:

    visninger / bøker / new.html.erb

    Legg til bok

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

    visninger / bøker / _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 %>

    Med dette oppsettet kan du allerede begynne å utføre opplastinger, men det er også en god idé å introdusere noen valideringer også.

    Legge til valideringer

    Valideringer i Paperclip kan skrives med gamle hjelpere som validates_attachment_presence og validates_attachment_content_type eller ved å ansette validates_attachment metode for å definere flere regler samtidig. La oss holde fast ved det sistnevnte alternativet:

    modeller / book.rb

     validates_attachment: image, content_type: content_type: /\Aimage\/.*\z/, størrelse: mindre_: 1.megabyte

    Koden er veldig enkel, som du kan se. Vi krever at filen skal være et bilde mindre enn 1 megabyte i størrelse. Merk at hvis valideringen mislykkes, vil ingen etterbehandling bli utført. Paperclip har allerede noen feilmeldinger angitt for det engelske språket, men hvis du vil støtte andre språk, inkluderer du paperclip-i18n-perlen i din Gemfile.

    En annen viktig ting å nevne er at Paperclip krever at du validerer innholdstype eller filnavn for alle vedlegg, ellers vil det oppstå en feil. Hvis du er 100% sikker på at du ikke trenger slike valideringer (som er et sjeldent tilfelle), bruk do_not_validate_attachment_file_type å eksplisitt si hvilke felt som ikke bør kontrolleres.

    Vi har lagt til valideringer, la oss også vise feilmeldinger i vårt skjema:

    visninger / delt / _errors.html.erb

    <% if object.errors.any? %> 

    Noen feil ble funnet:

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

    visninger / bøker / _form.html.erb

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

    Viser bilder

    Ok, så nå skal de opplastede bildene vises på en eller annen måte. Dette gjøres ved å bruke IMAGE_TAG hjelper og a url metode. Lage en vise fram utsikt:

    visninger / bøker / show.html.erb

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

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

    <%= @book.description %>

    Vi viser bare et bilde hvis det virkelig finnes på stasjonen. Videre, hvis du bruker skylagring, vil Paperclip utføre en nettverksforespørsel og sjekke filens eksistens. Selvfølgelig kan denne operasjonen ta litt tid, så du kan bruke nåværende? eller fil? metoder istedenfor: de vil bare sørge for at image_file_name feltet er fylt med noe innhold.

    URI Obfuscation

    Som standard lagres alle vedlegg inne i offentlig / system mappe, så du vil sannsynligvis utelukke den fra versjonskontrollsystemet: 

    .gitignore

    offentlig / system

    Å vise en full URI til filen kan imidlertid ikke alltid være en god ide, og du må kanskje forvirre det på en eller annen måte. Den enkleste måten å aktivere obfuscation er ved å gi to parametere til has_attached_file metode:

    modeller / book.rb

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

    De riktige verdiene blir interpolert inn i url automatisk. hash_secret er et obligatorisk felt, og den enkleste måten å generere den på er å bruke:

    skinner hemmelig

    Arbeide med stiler

    I mange tilfeller er det foretrukket å vise et miniatyrbilde med en forhåndsdefinert bredde og høyde for å lagre båndbredde. Paperclip løser dette ved å bruke stiler: hver stil har et navn og et sett med regler, som dimensjoner, format, kvalitet osv.

    Anta at vi vil ha det opprinnelige bildet og dets miniatyrbilde skal konverteres til JPEG-format. Miniatyrbildet skal beskjæres til 300x300px:

    modeller / book.rb

     has_attached_file: bilde, stiler: thumb: ["300x300 #",: jpeg], original: [: jpeg]

    # er en geometrisk innstilling som betyr: "Beskjære om nødvendig samtidig som du opprettholder aspektforhold."

    Vi kan også tilby flere konverteringsalternativer for hver stil. For eksempel, la oss gi 70% kvalitet for tommelen mens du fjerner alle metadata og 90% kvalitet for det opprinnelige bildet for å gjøre det litt mindre:

    modeller / book.rb

     has_attached_file: bilde, stiler: thumb: ["300x300 #",: jpeg], original: [: jpeg], convert_options: thumb: "-quality 70-strip", original: "-kvalitet 90"

    Hyggelig! Vis miniatyrbildet og gi lenken til det opprinnelige bildet:

    visninger / bøker / show.html.erb

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

    Merk at i motsetning til Carrierwave, for eksempel, kan Paperclip ikke tillate deg å skrive @ book.image.thumb.url.

    Hvis du av en eller annen grunn ønsker å oppdatere opplastede bilder manuelt, kan du bruke følgende kommandoer til å oppdatere bare miniatyrer, legge til manglende stiler eller oppdatere alle bilder:

    • rake paperclip: refresh: thumbnails CLASS = Book
    • rake paperclip: refresh: missing_styles CLASS = Book
    • rake paperclip: refresh CLASS = Book

    Lagre filer i skyen

    Som alle lignende løsninger, kan du med Paperclip laste opp filer til skyen. Ut av esken har den støtte til S3 og Fog-adaptere, men det finnes også tredjeparts edelstener for Azure og Dropbox. I denne delen vil jeg vise deg hvordan du integrerer Paperclip med Amazon S3. Først, slipp i aws-sdk-perlen:

    perle 'aws-sdk'

    Installer den:

    bunt installasjon

    Deretter gir du et nytt sett med alternativer til has_attached_file metode:

    modeller / book.rb

     has_attached_file: bilde, stiler: thumb: ["300x300 #",: jpeg], original: [: jpeg], convert_options: thumb: "-quality 70-strip", original: "-kvalitet 90", lagring :: s3, s3_credentials: access_key_id: ENV ["S3_KEY"], secret_access_key: ENV ["S3_SECRET"], bøtte: ENV ["S3_BUCKET"], s3_region: ENV ["S3_REGION"]

    Her stikker jeg til dotenv-skinnene perlen for å sette miljøvariabler. Du kan gi alle verdier direkte inn i modellen, men ikke gjøre den offentlig tilgjengelig.

    Det som er interessant er det s3_credentials aksepterer også en bane til en YAML-fil som inneholder nøklene og et bøttenavn. Videre kan du angi forskjellige verdier for forskjellige miljøer som dette: 

    utvikling: access_key_id: key1 secret_access_key: secret1 produksjon: access_key_id: key2 secret_access_key: secret2

    Det er det! Alle filene du laster opp, ligger nå i din S3-bøtte.

    Sikring av filer i skyen

    Anta at du ikke vil at de opplastede filene dine skal være tilgjengelige for alle. Som standard er alle opplastinger i skyen merket som offentlige, noe som betyr at alle kan åpne filen via direkte koblingen. Hvis du ønsker å presentere noen autorisasjonslogikk og sjekke hvem som kan se filen, må du sette inn s3_permissions alternativ til :privat som dette:

     has_attached_file: bilde, stiler: thumb: ["300x300 #",: jpeg], original: [: jpeg], convert_options: thumb: "-quality 70-strip", original: "-kvalitet 90", lagring :: s3, s3_credentials: access_key_id: ENV ["S3_KEY"], secret_access_key: ENV ["S3_SECRET"], bøtte: ENV ["S3_BUCKET"], s3_region: ENV ["S3_REGION"], s3_permissions:

    Nå, men ingen, unntatt for deg, vil kunne se filene. Derfor la oss lage en ny nedlasting handling for BooksController:

    books_controller.rb

     def nedlasting redirect_to @ book.image.expiring_url slutten

    Denne handlingen vil ganske enkelt omdirigere brukere til bildet via en utgående link. Ved hjelp av denne tilnærmingen kan du nå introdusere en autorisasjonslogikk ved hjelp av perler som CanCanCan eller Pundit.

    Ikke glem å sette medlemsruten:

    config / routes.rb

     ressurser: bøker gjør medlemmet få "nedlasting" slutten

    Hjelperen skal brukes slik:

    link_to ('View image', download_book_path (@book), mål: '_blank')

    Konklusjon

    Vi har kommet til slutten av denne artikkelen! I dag har vi sett Paperclip, en vedleggsløsningsløsning for Rails, i handling og diskutert hovedkonseptene. Det er mye mer til denne perlen, så vær sikker på å se dokumentasjonen.

    Jeg anbefaler også å besøke Paperclips wiki-side, da den presenterer en liste over "hvordan å" opplæringsprogrammer og en rekke lenker til tredjepartsmykker som støtter Azure og Cloudinary, og lar deg enkelt redusere opplastede filer.

    Takk for at du bodde hos meg og ser deg snart!