Acesta este un alt articol din seria "Încărcarea cu șine". Astăzi vom întâlni Carrierwave - una dintre cele mai populare soluții de încărcare a fișierelor pentru Rails. Îmi place Carrierwave, deoarece este ușor să începeți, are o mulțime de caracteristici din cutie și oferă zeci de articole "cum să" scrise de membrii comunității, astfel încât să nu vă pierdeți.
În acest articol, veți învăța cum să:
Codul sursă pentru acest articol este disponibil pe GitHub. Bucură-te de lectură!
Ca întotdeauna, începeți prin crearea unei noi aplicații Rails:
șine noi UploadingWithCarrierwave -T
Pentru acest demo voi folosi Rails 5.0.2. Rețineți că Carrierwave 1 acceptă numai Rails 4+ și Ruby 2. Dacă sunteți în continuare de echitatie pe Rails 3, apoi cârlig Carrierwave versiunea 0.11.
Pentru a vedea Carrierwave în acțiune, vom crea o aplicație de bloguri foarte simplă cu unic Post
model. Acesta va avea următoarele atribute principale:
titlu
(şir
)corp
(text
)imagine
(şir
) - acest câmp va conține o imagine (numele unui fișier, pentru a fi exact) atașat postuluiGenerați și aplicați o nouă migrare:
rails g model Titlul postului: body string: text image: string rails db: migrate
Creați câteva rute:
resurse: postări rădăcină la: 'posts # index'
De asemenea, creați un controler de bază:
clasa PostsController < ApplicationController before_action :set_post, only: [:show, :edit, :update] def index @posts = Post.order('created_at DESC') end def show end def new @post = Post.new end def create @post = Post.new(post_params) if @post.save redirect_to posts_path else render :new end end def edit end def update if @post.update_attributes(post_params) redirect_to post_path(@post) else render :edit end end private def post_params params.require(:post).permit(:title, :body, :image) end def set_post @post = Post.find(params[:id]) end end
Acum hai să construim index vedere:
Mesaje
<%= link_to 'Add post', new_post_path %> <%= render @posts %>
Și parțial corespondent:
<%= link_to post.title, post_path(post) %>
<%= truncate(post.body, length: 150) %>
<%= link_to 'Edit', edit_post_path(post) %>
Aici folosesc Rails-ul trunchia
pentru a afișa numai primele 150 de simboluri din post. Înainte de a crea alte vederi și o formă parțială, să integrăm mai întâi Carrierwave în aplicație.
Puneți într - o bijuterie nouă în Gemfile:
gem 'carrierwave', '~> 1.0'
Alerga:
instalare pachet
Carrierwave își stochează configurația în interior uploaderi care sunt incluse în modelele dvs. Pentru a genera un încărcător, utilizați următoarea comandă:
șinele generează imaginea încărcătorului
Acum, înăuntru app / uploaderi, veți găsi un nou fișier numit image_uploader.rb. Rețineți că aceasta conține câteva comentarii și exemple utile, astfel încât să puteți folosi pentru a începe. În acest demo vom folosi ActiveRecord, dar Carrierwave are, de asemenea, suport pentru Mongoid, Sequel și DataMapper.
Apoi, trebuie să includeți sau montură acest încărcător în model:
mount_uploader: imagine, ImageUploader
Încărcătorul are deja setări prestabilite, dar cel puțin trebuie să alegem unde vor fi stocate fișierele încărcate. Pentru moment, să folosim stocarea fișierelor:
stocare: fișier
Implicit, fișierele vor fi plasate în interiorul publice / încărcări directorul, deci cel mai bine este să-l excludeți de la sistemul de control al versiunilor:
publice / încărcări
Puteți, de asemenea, modifica store_dir
în interiorul dispozitivului dvs. de încărcare pentru a alege o altă locație.
În acest moment, putem crea o vizualizare nouă și o formă parțială pentru a începe încărcarea fișierelor:
Adăugați un post
<%= render 'form', post: @post %>
<%= form_for post do |f| %><%= f.label :title %> <%= f.text_field :title %><%= f.label :body %> <%= f.text_area :body %><%= f.label :image %> <%= f.file_field :image %><%= f.submit %> <% end %>
Rețineți că PostsController
nu trebuie modificată așa cum am permis deja imagine
atribut.
În cele din urmă, creați vizualizarea editare:
Editează postarea
<%= render 'form', post: @post %>
Asta e! Este posibil să bootați serverul și să încercați să creați o postare cu o imagine. Problema este că această imagine nu este vizibilă nicăieri, deci trecem la următoarea secțiune și adăugăm o pagină de prezentare!
Așadar, singura viziune pe care nu am creat-o încă este spectacol. Adăugați-l acum:
<%= link_to 'All posts', posts_path %><%= @post.title %>
<%= image_tag(@post.image.url, alt: 'Image') if @post.image? %><%= @post.body %>
<%= link_to 'Edit', edit_post_path(@post) %>
După cum puteți vedea, afișarea unui atașament este foarte ușoară: tot ce trebuie să faceți este să spuneți @ post.image.url
pentru a apuca adresa URL a unei imagini. Pentru a obține o cale către fișier, utilizați current_path
metodă. Rețineți că Carrierwave furnizează, de asemenea, o imagine?
metoda pentru a verifica dacă un atașament este prezent deloc ( imagine
metoda însăși nu se va mai întoarce niciodată zero
, chiar dacă fișierul nu este prezent).
Acum, după ce navigați la un post, ar trebui să vedeți o imagine, dar ar putea părea prea mare: la urma urmei, nu restricționăm dimensiunile oriunde. Bineînțeles, am fi putut scala imaginea în jos cu niște reguli CSS, dar este mult mai bine să generăm o miniatură după ce fișierul a fost încărcat. Acest lucru, totuși, necesită pași suplimentari.
Pentru a cultiva și a scala imagini, avem nevoie de un instrument separat. Out of the box Carrierwave are suport pentru pietrele RMagick și MiniMagick care, la rândul lor, sunt folosite pentru a manipula imaginile cu ajutorul ImageMagick. ImageMagick este o soluție open-source care vă permite să editați imagini existente și să generați altele noi, deci înainte de a continua trebuie să le descărcați și să le instalați. Apoi, aveți libertatea de a alege oricare dintre cele două pietre prețioase. Voi rămâne cu MiniMagick, deoarece este mult mai ușor de instalat și are un suport mai bun:
gem 'mini_magick'
Alerga:
instalare pachet
Apoi includeți MiniMagick în încărcătorul dvs.:
include CarrierWave :: MiniMagick
Acum, pur și simplu, trebuie să introducem o versiune nouă încărcătorului nostru. Conceptul de versiuni (sau stiluri) este utilizat în multe biblioteci de încărcare de fișiere; înseamnă pur și simplu că fișierele suplimentare bazate pe atașamentul original vor fi create cu, de exemplu, diferite dimensiuni sau formate. Introduceți o nouă versiune numită deget mare
:
versiune: degetul mare face procesul de resize_to_fill: [350, 350] sfârșit
Poate aveți la fel de multe versiuni pe care le doriți și, mai mult, versiunile pot fi chiar construite pe lângă celelalte:
versiune: small_thumb, from_version:: degetul mare face process resize_to_fill: [20, 20] end
Dacă ați încărcat deja unele imagini, nu vor fi disponibile miniaturi. Aceasta nu este o problemă, totuși, deoarece le puteți re-crea din consola Rails:
ramele c Post.find_each | post | post.image.recreate_versions! (: thumb) dacă post.image?
În cele din urmă, afișați miniatură cu un link spre imaginea originală:
<%= link_to(image_tag(@post.image.thumb.url, alt: 'Image'), @post.image.url, target: '_blank') if @post.image? %>
Porniți serverul și observați rezultatul!
În prezent, încărcarea noastră funcționează, dar nu validăm informațiile despre utilizatori, ceea ce este, desigur, rău. Atâta timp cât vrem să lucrăm numai cu imagini, să lăsăm în alb lista extensiilor .png, .jpg și .gif:
def extensie_whitelist% w (jpg jpeg gif png) sfârșit
De asemenea, puteți adăuga verificări pentru tipul de conținut prin definirea unui content_type_whitelist
metodă:
def content_type_whitelist / image \ / end
Alternativ, este posibilă listarea neagră a unor tipuri de fișiere, de exemplu executabile, prin definirea content_type_blacklist
metodă.
În afară de verificarea tipului și a extensiei unui fișier, lăsați-o să fie mai mică de 1 megabyte. Pentru a face acest lucru, vom solicita o validare suplimentară a fișierelor de bijuterii pentru ActiveModel:
gem "file_validators"
Instalați-l:
instalare pachet
Acum, introduceți validările dorite (rețineți că adaug, de asemenea, verificări pentru titlu
și corp
atribute):
validează: titlu, prezență: adevărat, lungime: minimum: 2 validează: corp, prezență: valid valide: imagine, file_size: less_than: 1.megabytes
Următorul lucru de făcut este să adăugați traduceri I18n pentru mesajele de eroare ale lui Carrierwave:
en: erori: mesaje: carrierwave_processing_error: "Nu se poate redimensiona imaginea". carrierwave_integrity_error: "Nu o imagine." carrierwave_download_error: "Imaginea nu a putut fi descărcată". extension_whitelist_error: "Nu aveți permisiunea de a încărca fișierele% extension, tipurile admise:% allowed_types" extension_blacklist_error: "Nu aveți permisiunea de a încărca fișiere% extension, tipuri interzise:% prohibited_types"
În prezent, nu afișăm erori de validare oriunde, deci să creăm o partajare partajată:
<% if object.errors.any? %>Au fost găsite unele erori:
Utilizați acest lucru parțial în interiorul formularului:
<%= render 'shared/errors', object: post %>
Acum încercați să încărcați unele fișiere nevalide și observați rezultatul. Ar trebui să funcționeze, dar dacă alegeți un fișier valid și nu completați titlul sau corpul, atunci verificările vor eșua și va apărea o eroare. Cu toate acestea, câmpul fișierului va fi șters și utilizatorul va trebui să aleagă din nou imaginea, ceea ce nu este foarte convenabil. Pentru ao remedia, trebuie să adăugăm un alt câmp la formular.
Fișierele persistente în redisplay-urile de formă sunt de fapt destul de ușor. Tot ce trebuie să faceți este să adăugați un nou câmp ascuns și să îl permiteți în interiorul controlerului:
<%= f.label :image %> <%= f.file_field :image %>
<%= f.hidden_field :image_cache %>
params.require (: post) .permite (: titlu,: corp, imagine, imagine_cache)
Acum image_cache
vor fi populate automat și imaginea nu va fi pierdută. Poate fi util să afișați și o miniatură, astfel încât utilizatorul să înțeleagă că imaginea a fost procesată cu succes:
<% if post.image? %> <%= image_tag post.image.thumb.url %> <% end %>
O altă caracteristică foarte comună este capacitatea de a elimina fișiere atașate la editarea unei înregistrări. Cu Carrierwave, implementarea acestei funcții nu este o problemă. Adăugați o nouă casetă de selectare în formular:
<% if post.image? %> <%= image_tag post.image.thumb.url %><%= label_tag :remove_image do %> Eliminați imaginea <%= f.check_box :remove_image %> <% end %><% end %>
Și permiteți-i remove_image
atribut:
params.require (: post) .permite (: titlu,: corp,: imagine,: remove_image,: image_cache)
Asta e! Pentru a elimina manual imaginea, utilizați remove_image!
metodă:
@ post.remove_image!
Carrierwave oferă, de asemenea, o caracteristică foarte interesantă din cutie: abilitatea de a încărca fișiere din locații îndepărtate prin URL-ul lor. Să prezentăm această abilitate acum prin adăugarea unui câmp nou și permițând atributul corespunzător:
<%= f.text_field :remote_image_url %> Introduceți URL-ul unei imagini
params.require (: post) .permite (: titlu,: body,: image,: remove_image,: image_cache,: remote_image_url)
Cat de tare e asta? Nu este nevoie să faceți nicio modificare și puteți testa imediat această caracteristică!
Să presupunem că dorim ca postul nostru să aibă mai multe atașamente disponibile. Cu configurarea actuală nu este posibil, dar, din fericire, Carrierwave susține un astfel de scenariu, de asemenea. Pentru a implementa această caracteristică, trebuie să adăugați un câmp serializat (pentru SQLite) sau un câmp JSON (pentru Postgres sau MySQL). Prefer cea de-a doua opțiune, așa că acum trecem la un nou adaptor de bază de date. Îndepărtați gemul sqlite3 din Gemfile și adăugați pg în schimb:
gem "pg"
Instalați-l:
instalare pachet
Modificați configurația bazei de date astfel:
implicit: & adaptor implicit: postgresql piscină: 5 timeout: 5000 dezvoltare: <<: *default database: upload_carrier_dev username: 'YOUR_USER' password: 'YOUR_PASSWORD' host: localhost
Creați baza de date Postgres corespunzătoare, apoi generați și aplicați migrarea:
rails g migrare add_attachments_to_posts atașamente: json rails db: migrate
Dacă preferați să respectați SQLite, urmați instrucțiunile din documentația Carrierwave.
Acum, montați încărcătoarele (rețineți forma plurală):
mount_uploaders: attachments, ImageUploader
Folosesc același uploader pentru atașamente, dar, desigur, puteți genera unul nou cu o configurație diferită.
Adăugați câmpul cu mai multe fișiere în formularul dvs.:
<%= f.label :attachments %> <%= f.file_field :attachments, multiple: true %>
Atâta timp cât atașamente
câmpul va conține o matrice, ar trebui permisă în felul următor:
params.require (: post) .permit (: title,: body, image, remove_image, image_cache, remote_image_url, attachments: []
În cele din urmă, puteți repeta atașamentele postării și le puteți afișa ca de obicei:
<% if @post.attachments? %>
Rețineți că fiecare atașament va avea o miniatură așa cum este configurată în versiunea noastră ImageUploader
. Frumos!
Lipirea cu stocarea fișierelor nu este întotdeauna convenabilă și / sau posibilă, deoarece, de exemplu, pe Heroku nu este posibilă stocarea de fișiere personalizate. Prin urmare, s-ar putea să întrebați cum să vă căsătoriți cu Carrierwave cu spațiul de stocare Amazon S3? Ei bine, este și o sarcină destul de ușoară. Carrierwave depinde de gem-aws bijuterie pentru a pune în aplicare această caracteristică:
bijuterie "ceata-aws"
Instalați-l:
instalare pachet
Să creați un inițializator pentru Carrierwave și să configurați stocarea cloud la nivel global:
CarrierWave.configure do | config | config.fog_provider = 'fog / aws' config.fog_credentials = furnizor: 'AWS', aws_access_key_id: ENV ['S3_KEY'], aws_secret_access_key: ENV ['S3_SECRET'], regiune: ENV ['S3_REGION'], config. fog_directory = ENV ['S3_BUCKET'] sfârșit
Există și alte opțiuni disponibile, care pot fi găsite în documentație.
Folosesc gheața Dotenv-Rail pentru a seta variabilele de mediu într-un mod sigur, dar puteți alege orice altă opțiune. Cu toate acestea, asigurați-vă că perechea de chei S3 nu este disponibilă public, deoarece altfel oricine poate încărca ceva în galeata dvs.!
Apoi, înlocuiți stocare: fișier
line cu:
depozitare: ceață
În afară de S3, Carrierwave acceptă încărcări în Google Storage și Rackspace. Aceste servicii sunt ușor de configurat, de asemenea.
Asta este pentru ziua de azi! Am acoperit toate caracteristicile majore ale Carrierwave, iar acum puteți să o utilizați în proiectele dvs. Dispune de câteva opțiuni suplimentare, așa că răsfoiți documentația.
Dacă sunteți blocați, nu ezitați să vă postați întrebările. De asemenea, ar putea fi util să aruncăm o privire asupra wiki-ului Carrierwave, care găzduiește articole "cum să" să răspundă la multe întrebări frecvente.
Deci vă mulțumesc că ați rămas împreună cu mine și că ați fost fericit de codat!