Ruby Diary #26: Dove salvare le immagini in Rails

Mercoledì 2 Gennaio 2008 - 10:35

di Simone Carletti

Ruby

Non ho aspettato più di qualche ora ad introdurre >respond_to() nell’applicazione Rails. Nel mio caso utilizzo un unico metodo per mostrare un’anteprima di una immagine. Se la richiesta è HTML mostro la cornice che impagina la thumbnail, in alternativa se la richiesta è di tipo immagine (png) restituisco l’immagine stessa. Per ogni altra richiesta restituisco 404.

A grandi linee, il codice assomiglia a questo:

def show

    # validate URI
    begin
        @uri = URI.parse('http://' + params[:uri])
    rescue
        raise_404(); return
    end

    # more code here and get image_path

    respond_to do |type|
        # html request
        type.html { render } # default template

        # image requests
        type.png  { send_file(image_path, :disposition  => 'inline') }

        # all
        type.all  { raise_404(); return }
    end

end

Come potete notare, utilizzo send_file() per inviare il contenuto del file e non fornisco direttamente il suo percorso per motivi di sicurezza. Questo approccio funziona però ad una condizione, ovvero che il controller che gestisce l’immagine — nel mio caso show — si trovi al di fuori di public/images.

public/images è infatti una cartella speciale il Rails. I file contenuti all’interno non sono soggetti a routing ma vengono direttamente restituiti al client.

Attenzione quindi. Se scriverete nel vostro file config/routes.rb una regola tipo

# display image
map.image '/images/thubmnail/:uri',
  :controller =>  'thumbnail',
  :action     =>  'show'

non verrà mai eseguita con una configurazione di Rails predefinita. O almeno, questo mi risulta al momento. L’accendiamo?

Tags:

Categoria: Ruby | Permalink

Commenti

1

Si, in realtà questo ragionamento funziona per tutto quanto si trovi nella sottocartella ‘public’; questo spiega anche il funzionamento del più semplice sistema di caching presente in Rails, che non fà altro che salvare l’output del rendering in un file all’interno della cartella public in modo che sia raggiungibile direttamente dal webserver senza l’intervento del framework.

# - postato da Sandro Paganotti - 04 Gennaio 2008 - 09:53

2

In realtà i file nella cartella ‘public’ evitano l’esecuzione di action tramite routing, ma qualsiasi richiesta è soggetta a routing se necessario.

Nel file config/routes.rb:

map.image 'images/thumbnails/:url.:format',
  :controller =>  'thumbnail',
  :action     =>  'show'

Nel file ‘app/controllers/thumbnails_controller.rb:

def show
  raise "Sono nel controller con filename "   params[:filename]
    " e format "   params[:format]
end

Ora da browser accedendo a
http://localhost:3000/images/t....._rocks.png
passiamo per il controller:

RuntimeError in ThumbnailController#show

Sono nel controller con filename rails_rocks e format png
...
Request

Parameters:

{"format"=>"png",
 "filename"=>"rails_rocks"}

Come giustamente dicevate la cartella public viene controllata per verificare se è presente un file statico da servire a fronte di una richiesta; se il file non viene trovato ActionPack individua tramite il file ‘config/routes.rb’ controller, action e parametri da invocare per rispondere alla richiesta.

Per sanità mentale ti consiglierei di dedicare la cartella ‘public/images’ a file statici di immagini e cambiare il route del tuo controller.

A meno che tu non possa creare i thumbnail proattivamente come file statici (ad esempio quando viene caricata un’immagine sul server viene creato anche il rispettivo thumbnail) e che i file non possano essere resi pubblici.

In questo caso depositerei i thumbnails nella cartella /images/thumbnails/ con un bel File.open o qualcosa di simile così da sfruttare eventuali configurazioni del web server e il sistema di distribuzione degli asset su più server resa disponibile in Rails > 2 (che funziona davvero bene).

# - postato da ynw - 06 Gennaio 2008 - 18:59

Inserisci il tuo commento:





(puoi usare i seguenti tag HTML per formattare il testo -
a href, b, i, br/, p, strong, em, ul, ol, li, blockquote, pre):

 

Anteprima del commento