Uploaden met rails en paperclip

Dit is het laatste artikel in de serie 'Uploaden met rails'. In de afgelopen maanden hebben we al gesproken over de pareltjes van de Shrine, Dragonfly en Carrierwave. De gast van vandaag is Paperclip van Thoughtbot, een bedrijf dat edelstenen beheert zoals FactoryGirl en Bourbon.

Paperclip is waarschijnlijk de populairste oplossing voor het beheren van bijlagen voor Rails (meer dan 13 miljoen downloads) en dat is niet voor niets: het heeft veel functies, een geweldige community en grondige documentatie. Dus hopelijk bent u benieuwd naar meer informatie over dit juweeltje!

In dit artikel leert u hoe u:

  • Bereid je voor op de installatie van Paperclip
  • Integreer Paperclip in een Rails-applicatie
  • Voeg bijlage-validaties toe
  • Genereer miniaturen en verwerk afbeeldingen
  • Obfuscate URL's
  • Winkel bijlagen op Amazon S3
  • Beveilig bestanden in de cloud door autorisatielogica te introduceren

De broncode voor dit artikel is beschikbaar op GitHub.

Voorbereidende werkzaamheden

Voordat we in de code duiken, bespreken we eerst enkele kanttekeningen die u moet weten om met succes met Paperclip te werken:

  • De nieuwste versie van Paperclip ondersteunt Rails 4.2+ en Ruby 2.1+. Dit juweel kan ook zonder Rails worden gebruikt.
  • ImageMagick moet op uw pc zijn geïnstalleerd (het is beschikbaar voor alle grote platforms) en Paperclip zou er toegang toe moeten hebben.
  • De het dossier opdracht moet beschikbaar zijn via de opdrachtregel. Voor Windows is het beschikbaar via Development Kit, dus volg deze instructies als je DevKit nog niet hebt geïnstalleerd.

Wanneer u klaar bent, ga je gang en maak een nieuwe Rails-applicatie aan (ik zal Rails 5.0.2 gebruiken) zonder het standaard testsuite:

rails nieuw UploadingWithPaperclip -T

Integratie van Paperclip

Laat de Paperclip-juweel vallen:

Gemfile

gem "paperclip", "~> 5.1"

Installeer het:

bundel installeren

Stel dat we een boekenplank-applicatie maken die een lijst met boeken presenteert. Elk boek heeft een titel, een beschrijving, de naam van een auteur en een omslagafbeelding. Om te beginnen, genereert en past u de volgende migratie toe:

rails g model Boektitel: stringbeschrijving: tekstafbeelding: auteur van bijlage: stringrails db: migreren

Merk op gehechtheid type dat door Paperclip voor ons wordt gepresenteerd. Onder de motorkap gaan we vier velden maken:

  • image_file_name
  • IMAGE_FILE_SIZE
  • image_content_type
  • image_updated_at

In tegenstelling tot de juwelen van het altaar en de drager, heeft Paperclip geen afzonderlijk bestand met configuraties. Alle instellingen worden binnen het model zelf gedefinieerd met behulp van de has_attached_file methode, dus voeg het nu toe:

modellen / book.rb

has_attached_file: afbeelding

Voordat we naar het hoofdgedeelte gaan, maken we ook een controller samen met enkele weergaven en routes.

De controller, weergaven en routes maken

Onze controller zal heel eenvoudig zijn:

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

Hier is een inhoudsopgave weergave en een gedeeltelijke:

views / boeken / index.html.erb

Boekenplank

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

views / boeken / _book.html.erb

  • <%= link_to book.title, book_path(book) %> door <%= book.author %>
  • Nu de routes:

    config / routes.rb

    Rails.application.routes.draw do resources: books root to: 'books # index' end 

    Leuk! Laten we nu naar het hoofdgedeelte gaan en de code coderen nieuwe actie en een formulier.

    Bestanden uploaden

    Al met al is uploaden met Paperclip eenvoudig. U hoeft alleen het overeenkomstige kenmerk toe te staan ​​(in ons geval is dat het beeld attribuut, en we hebben dit al toegestaan) en presenteren een bestandsveld in uw formulier. Laten we het nu doen:

    views / boeken / new.html.erb

    Voeg boek toe

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

    views / boeken / _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 %>

    Met deze opstelling kunt u al beginnen met het uitvoeren van uploads, maar het is een goed idee om ook enkele validaties te introduceren.

    Validaties toevoegen

    Validaties in Paperclip kunnen worden geschreven met behulp van oude helpers zoals validates_attachment_presence en validates_attachment_content_type of door de validates_attachment methode om meerdere regels tegelijkertijd te definiëren. Laten we bij de laatste optie blijven:

    modellen / book.rb

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

    De code is heel eenvoudig, zoals u kunt zien. We vereisen dat het bestand een afbeelding van minder dan 1 megabyte is. Merk op dat als de validatie mislukt, er geen nabewerking zal plaatsvinden. Paperclip heeft al enkele foutmeldingen voor de Engelse taal, maar als je andere talen wilt ondersteunen, voeg je de paperclip-i18n edelsteen toe aan je Gemfile.

    Een ander belangrijk ding om te vermelden is dat Paperclip vereist dat u het inhoudstype of de bestandsnaam van alle bijlagen valideert, anders zal er een fout optreden. Als u er 100% zeker van bent dat u dergelijke validaties niet nodig hebt (wat een zeldzaam geval is), gebruik dan do_not_validate_attachment_file_type om expliciet te zeggen welke velden niet moeten worden gecontroleerd.

    Nadat we validaties hebben toegevoegd, laten we ook foutmeldingen in onze vorm weergeven:

    views / shared / _errors.html.erb

    <% if object.errors.any? %> 

    Sommige fouten zijn gevonden:

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

    views / boeken / _form.html.erb

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

    Afbeeldingen weergeven

    Oké, dus nu moeten de geüploade afbeeldingen op een of andere manier worden weergegeven. Dit wordt gedaan met behulp van de image_tag helper en a url methode. Maak een laten zien uitzicht:

    views / boeken / show.html.erb

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

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

    <%= @book.description %>

    We geven een afbeelding alleen weer als deze echt op de schijf aanwezig is. Bovendien, als u cloudopslag gebruikt, zal Paperclip een netwerkverzoek uitvoeren en het bestaan ​​van het bestand controleren. Natuurlijk kan deze bewerking enige tijd duren, dus u kunt de aanwezig? of het dossier? methoden in plaats daarvan: ze zullen er eenvoudig voor zorgen dat het image_file_name veld bevat een aantal inhoud.

    URI Obfuscation

    Standaard worden alle bijlagen opgeslagen in de public / systeem map, dus u wilt hem waarschijnlijk uitsluiten van het versiecontrolesysteem: 

    .gitignore

    public / systeem

    Het is echter niet altijd een goed idee om een ​​volledige URI voor het bestand weer te geven, en mogelijk moet u het op de een of andere manier verdoezelen. De eenvoudigste manier om verduistering mogelijk te maken, is door twee parameters aan de has_attached_file-methode:

    modellen / book.rb

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

    De juiste waarden worden geïnterpoleerd naar de url automatisch. hash_secret is een verplicht veld, en de gemakkelijkste manier om het te genereren is door het gebruik van:

    rails geheim

    Werken met stijlen

    In veel gevallen heeft het de voorkeur om de miniatuur van een afbeelding weer te geven met een vooraf gedefinieerde breedte en hoogte om bandbreedte te besparen. Paperclip lost dit op met behulp van stijlen: elke stijl heeft een naam en een reeks regels, zoals afmetingen, formaat, kwaliteit, enz.

    Stel dat we willen dat de originele afbeelding en de miniatuur ervan worden geconverteerd naar JPEG-indeling. De miniatuur moet worden bijgesneden tot 300 x 300 pixels:

    modellen / book.rb

     has_attached_file: afbeelding, stijlen: thumb: ["300x300 #",: jpeg], original: [: jpeg]

    # is een geometrie-instelling, wat betekent: "Snijd indien nodig bij terwijl u de beeldverhouding handhaaft."

    We kunnen ook extra conversieopties bieden voor elke stijl. Laten we bijvoorbeeld 70% kwaliteit voor duimen geven, terwijl alle metadata en 90% kwaliteit voor de originele afbeelding worden verwijderd om het een beetje kleiner te maken:

    modellen / book.rb

     has_attached_file: image, styles: thumb: ["300x300 #",: jpeg], original: [: jpeg], convert_options: thumb: "-kwaliteit 70 -strip", origineel: "-kwaliteit 90"

    Leuk! Geef de miniatuur weer en geef de link naar de originele afbeelding:

    views / boeken / show.html.erb

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

    Merk op dat Paperclip, in tegenstelling tot Carrierwave, je niet toestaat te schrijven @ book.image.thumb.url.

    Als u om de een of andere reden geüploade afbeeldingen handmatig wilt bijwerken, kunt u de volgende opdrachten gebruiken om alleen miniaturen te vernieuwen, ontbrekende stijlen toe te voegen of alle afbeeldingen te vernieuwen:

    • hark paperclip: vernieuwen: miniaturen KLASSE = Boek
    • hark paperclip: refresh: missing_styles KLASSE = Boek
    • hark paperclip: ververs CLASS = Boek

    Bestanden opslaan in de cloud

    Zoals alle vergelijkbare oplossingen, kun je met Paperclip bestanden uploaden naar de cloud. Out of the box biedt ondersteuning voor de S3- en Fog-adapters, maar er zijn ook edelstenen van derden voor Azure en Dropbox. In deze sectie zal ik je laten zien hoe je Paperclip integreert met Amazon S3. Laat eerst de aws-sdk edelsteen vallen:

    gem 'aws-sdk'

    Installeer het:

    bundel installeren

    Geef vervolgens een nieuwe set opties aan de has_attached_file methode:

    modellen / book.rb

     has_attached_file: afbeelding, stijlen: thumb: ["300x300 #",: jpeg], original: [: jpeg], convert_options: thumb: "-kwaliteit 70 -strip", origineel: "-kwaliteit 90", opslag :: s3, s3_credentials: access_key_id: ENV ["S3_KEY"], secret_access_key: ENV ["S3_SECRET"], bucket: ENV ["S3_BUCKET"], s3_region: ENV ["S3_REGION"]

    Hier blijf ik bij de dotenv-rails-edelsteen om omgevingsvariabelen in te stellen. U kunt alle waarden rechtstreeks in het model opgeven, maar maak deze niet openbaar beschikbaar.

    Wat interessant is, is dat s3_credentials accepteert ook een pad naar een YAML-bestand met uw sleutels en een bucketnaam. Bovendien kunt u verschillende waarden instellen voor verschillende omgevingen zoals deze: 

    ontwikkeling: access_key_id: key1 secret_access_key: secret1 production: access_key_id: key2 secret_access_key: secret2

    Dat is het! Alle bestanden die u uploadt, bevinden zich nu in uw S3-bucket.

    Bestanden beveiligen in de cloud

    Stel dat u niet wilt dat uw geüploade bestanden beschikbaar zijn voor iedereen. Standaard worden alle uploads naar de cloud als openbaar gemarkeerd, wat betekent dat iedereen het bestand via de directe link kan openen. Als u enkele autorisatielogica wilt introduceren en wilt controleren wie het bestand kan bekijken, stelt u de s3_permissions optie om :privaat zoals dit:

     has_attached_file: afbeelding, stijlen: thumb: ["300x300 #",: jpeg], original: [: jpeg], convert_options: thumb: "-kwaliteit 70 -strip", origineel: "-kwaliteit 90", opslag :: 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

    Nu zal niemand behalve u de bestanden kunnen zien. Laten we daarom een ​​nieuw maken downloaden actie voor de BooksController:

    books_controller.rb

     def download redirect_to @ book.image.expiring_url end

    Met deze actie worden gebruikers eenvoudig doorverwezen naar de afbeelding via een verlopende link. Met deze aanpak kunt u nu elke autorisatielogica introduceren met behulp van edelstenen zoals CanCanCan of Pundit.

    Vergeet niet om de ledenroute in te stellen:

    config / routes.rb

     middelen: boeken krijgen leden wel 'download'-end

    De helper moet als volgt worden gebruikt:

    link_to ('View image', download_book_path (@book), target: '_blank')

    Conclusie

    We zijn aan het einde van dit artikel gekomen! Vandaag hebben we Paperclip, een oplossing voor attachment management voor Rails, in actie gezien en de belangrijkste concepten besproken. Er is veel meer in dit juweeltje, dus zorg ervoor dat je de documentatie ervan bekijkt.

    Ik raad ook aan de wikipagina van Paperclip te bezoeken, aangezien deze een lijst met tutorials "hoe" biedt en een heleboel links naar edelstenen van derden die Azure en Cloudinary ondersteunen, zodat je geüploade bestanden gemakkelijk kunt verkleinen.

    Bedankt dat je bij me bent gebleven en tot snel!