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:
De broncode voor dit artikel is beschikbaar op GitHub.
Voordat we in de code duiken, bespreken we eerst enkele kanttekeningen die u moet weten om met succes met Paperclip te werken:
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
Laat de Paperclip-juweel vallen:
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:
has_attached_file: afbeelding
Voordat we naar het hoofdgedeelte gaan, maken we ook een controller samen met enkele weergaven en routes.
Onze controller zal heel eenvoudig zijn:
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:
Boekenplank
<%= link_to 'Add book', new_book_path %>
Nu de routes:
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.
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:
Voeg boek toe
<%= 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 %>
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 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:
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:
<% if object.errors.any? %>Sommige fouten zijn gevonden:
<%= render 'shared/errors', object: book %>
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:
<%= @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.
Standaard worden alle bijlagen opgeslagen in de public / systeem map, dus u wilt hem waarschijnlijk uitsluiten van het versiecontrolesysteem:
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
:
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
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:
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:
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:
<%= 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
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:
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.
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
:
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:
middelen: boeken krijgen leden wel 'download'-end
De helper moet als volgt worden gebruikt:
link_to ('View image', download_book_path (@book), target: '_blank')
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!