Le gem principale per lβupload di file Γ¨ CarrierWave
Per prima cosa Γ¨ necessario creare un oggetto Uploader
:
rails generate uploader Avatar
che crea il seguente file
class AvatarUploader < CarrierWave::Uploader::Base
storage :file
end
CarrierWave fornisce un metodo store
per lo storage permanenete e un metodo cache
per lo storage temporaneo.
Una volta ceh Γ¨ stato definito un uploader come AvatarUploader, posso salvare un file (o reperirlo) con le seguenti istruzioni:
uploader = AvatarUploader.new
uploader.store!(my_file)
uploader.retrieve_from_store!('my_file.png')
Configurazione del model
Devo agginugere una colonna al model in cui voglio inserire lβuploader:
add_column :users, :avatar, :string
e poi, nella dichiarazione del model, scrivo:
class User < ActiveRecord::Base
mount_uploader :avatar, AvatarUploader
end
Ora posso memorizzare i file assegnandoli come attributi del model:
u = User.new
u.avatar = params[:file]
u.save!
Estensioni ammesse
Per poter permettere file solo con determinate estensioni basta aggiungere il metodo extension_white_list
allβuploader
def extension_white_list
%w(jpg jpeg gif png)
end
Versioni per il file
Voglio poter permettere varie versioni dello stesso file, con caratteristiche diverse (un classico esempio sono le thumbnail). Per esempio, vogliamo che unβimmagine caricata non sia mai piΓΉ larga di 800x800, inoltre creo automaticamente una thumb croppata a 200x200 Aggiorno lβuploader cosΓ¬:
class MyUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
process :resize_to_fit => [800, 800]
version :thumb do
process :resize_to_fill => [200,200]
end
end
Ottengo quindi:
uploader = AvatarUploader.new
uploader.store!(my_file) # size: 1024x768
uploader.url # => '/url/to/my_file.png' # size: 800x600
uploader.thumb.url # => '/url/to/thumb_my_file.png' # size: 200x200
Versioni innestate
Posso anche innestare le versioni:
class MyUploader < CarrierWave::Uploader::Base
version :animal do
version :human
version :monkey
version :llama
end
end
Versioni condizionali
Posso creare una versione di un file solo se il model (variabile model
, riferita al model a cui lβuploader Γ¨ riferito) soddisfa determinate caratteristiche
class MyUploader < CarrierWave::Uploader::Base
version :human, :if => :is_human?
version :monkey, :if => :is_monkey?
version :banner, :if => :is_landscape?
protected
def is_human? picture
model.can_program?(:ruby)
end
def is_monkey? picture
model.favorite_food == 'banana'
end
def is_landscape? picture
image = MiniMagick::Image.open(picture.path)
image[:width] > image[:height]
end
end
Mantenere un upload anche se la validazione fallisce
In alcune piattaforme, il file caricato scompare se la validazione del form di inserimento fallisce obbligando lβutente a ricaricare tutto. Questo comportamento Γ¨ avitabile usando un campo hidden avatar_cache
(assumendo che il nome dellβupload sia avatar
) che verrΓ valorizzato con il file giΓ caricato dallβutente senza che questo se ne accorga.
Posso inserire una thumnail, per esempio, per far capire allβutente che il file esiste ed Γ¨ stato caricato correttamente
<%= form_for @user, :html => {:multipart => true} do |f| %>
<p>
<label>My Avatar</label>
<%= image_tag(@user.avatar_url) if @user.avatar? %>
<%= f.file_field :avatar %>
<%= f.hidden_field :avatar_cache %>
</p>
<% end %>
Rimuovere un file caricato
Posso o chiamare il metodo remove_avatar!
da controller, oppure usare un checkbox di questo tipo nelle views:
<%= form_for @user, :html => {:multipart => true} do |f| %>
<p>
<label>My Avatar</label>
<%= image_tag(@user.avatar_url) if @user.avatar? %>
<%= f.file_field :avatar %>
</p>
<p>
<label>
<%= f.check_box :remove_avatar %>
Remove avatar
</label>
</p>
<% end %>
Caricare un file tramite un URL
<%= form_for @user, :html => {:multipart => true} do |f| %>
<p>
<label>My Avatar URL:</label>
<%= image_tag(@user.avatar_url) if @user.avatar? %>
<%= f.text_field :remote_avatar_url %>
</p>
<% end %>
Fornire un URL di default
Spesso, sopratutto con le immagini, conviene fornire un URL di defualt nel caso in cui lβutente non carichi nessun file. Per fornire un url di default da utilizzare posso usare il metodo default_url nellβuploader
class MyUploader < CarrierWave::Uploader::Base
def default_url
"/images/fallback/" + [version_name, "default.png"].compact.join('_')
end
end
Configurazioni
Per configurare CarrierWave basta creare il file config/initializers/carrierwave.rb
e inserirvi config come questa di esempio:
CarrierWave.configure do |config|
config.permissions = 0666
config.storage = :s3
end
Test
Conviene testare utilizzando uno storage locale e non remoto, con la seguente configurazione:
if Rails.env.test? or Rails.env.cucumber?
CarrierWave.configure do |config|
config.storage = :file
config.enable_processing = false
end
end
Rspec
CarrierWave possiede dei matcher rspec molto comodi, di seguito un esempio:
require 'carrierwave/test/matchers'
describe MyUploader do
include CarrierWave::Test::Matchers
before do
MyUploader.enable_processing = true
@uploader = MyUploader.new(@user, :avatar)
@uploader.store!(File.open(path_to_file))
end
after do
MyUploader.enable_processing = false
end
context 'the thumb version' do
it "should scale down a landscape image to be exactly 64 by 64 pixels" do
@uploader.thumb.should have_dimensions(64, 64)
end
end
context 'the small version' do
it "should scale down a landscape image to fit within 200 by 200 pixels" do
@uploader.small.should be_no_larger_than(200, 200)
end
end
it "should make the image readable only to the owner and not executable" do
@uploader.should have_permissions(0600)
end
end
Amazon S3
Per permettere il caricamento su S3 Γ¨ necessaria la gem fog
, devo fornire i fog_credentials
e la fog_directory
in un initializer (ricorda che la fog_directory
deve essere creata prima)
Di seguito un esempio di configurazione per amazon S3:
CarrierWave.configure do |config|
config.fog_credentials = {
:provider => 'AWS', # required
:aws_access_key_id => 'xxx', # required
:aws_secret_access_key => 'yyy', # required
:region => 'eu-west-1' # optional, defaults to 'us-east-1'
}
config.fog_directory = 'name_of_directory' # required
config.fog_host = 'https://assets.example.com' # optional, defaults to nil
config.fog_public = false # optional, defaults to true
config.fog_attributes = {'Cache-Control'=>'max-age=315576000'} # optional, defaults to {}
end
Nellβuploader devo settare lo storage a :fog
:
class AvatarUploader < CarrierWave::Uploader::Base
storage :fog
end
Per ottenere lβurl del file memorizzato funziona in maniera trasparente il metodo url
dellβuploader
(CarrierWave::Uploader#url
)
carrierwave-aws
Al posto di fog
conviene usare carrierwave-aws che Γ¨ pensata solo per amazon, molto piΓΉ leggera e versatile.
Manipolare immagini
CarrierWave fornisce una semplice libreria di elaborazione immagini che permette di cambiarne il formato, ridimensionarleβ¦