2009-09-03 9 views
13

Quando si instradano le risorse in Rails, l'attributo di formato opzionale viene automaticamente aggiunto ai percorsi generati. Questo è così che la risorsa in questione può essere richiesta come XML, HTML, ecc. I formati effettivamente permessi sono solitamente descritti nel controller usando respond_to.Come limitare i formati di risorse nel file di percorsi di Rails

Ma in molti casi si desidera supportare solo HTML e sembra un sovraccarico scrivere respond_to :html in ogni azione in ogni controller. Sarebbe quindi bello se esistesse un modo per limitare i tipi di contenuto consentiti già durante la creazione delle rotte nel file routes.rb, ad es.

map.resources :users, :formats => :html 
map.resources :users, :formats => [:html, :xml] 
map.resources :users, :formats => {:index => :html, :show => [:html, :xml]}

C'è un modo per raggiungere questo obiettivo sia nativo o tramite un plug-in?

P.S. Il solito modo di aggirare questo problema è ignorare il problema e non utilizzare respond_to nelle azioni. Ma questo in realtà non limita i tipi di contenuti consentiti. Invece si aspetta solo che esista un modello nella directory views per ogni possibile tipo di contenuto. Se uno non esiste quando richiesto, il sistema genererà un errore HTTP 500.

risposta

1

In entrambi i casi, non si desidera un errore HTTP 500? Come nella seconda riga del tuo esempio, se qualcuno ha richiesto JSON anziché HTML o XML non è un codice di errore restituisce la risposta appropriata?

+1

No, significa 500 errore di qualcosa è andato storto sul server . Se un tipo di contenuto non è supportato non è un errore del server - si tratta di un errore del client (il client non avrebbe dovuto richiederlo). Un 406 sarebbe il codice di risposta corretto. Vedere "Codici di risposta HTTP": http://www.sitepoint.com/blogs/2008/02/04/restful-rails-part-i/ –

+0

Sicuramente se si intende tagare .xml o .html alla fine di l'URL e quel formato non sono supportati, quindi si dovrebbe restituire 404 non trovato. Sembra quasi impertinente ignorare l'uso di conneg creando URL per ogni tipo di contenuto, ma poi rubare il codice di risposta per quando non c'è un tipo di contenuto valido nell'intestazione accept! –

+0

Beh, potresti avere un punto - anche se questo è in realtà il modo in cui Rails funziona fuori dagli schemi. Ma tuttavia questo non è il punto della mia domanda. Vorrei comunque specificare questo in una posizione centrale (preferibilmente il file di percorsi), non importa se poi un 404 o un 406 viene restituito per errore –

3

Credo che siete in grado di fare qualcosa del genere:

respond_to do |format| 
    format.html 
    format.json { render :json => @things } 
    format.any { render :text => "Invalid format", :status => 403 } 
end 

Se l'utente richiede HTML o JSON si farà come si deve, ma qualsiasi altra cosa renderà il testo "Formato non valido".

+0

che funzionerebbe ma penso che voglia abbandonare il: format dai percorsi –

0

piuttosto che fare:

def some_action 
    ... 
    respond_to do |format| 
    format.html 
    format.json { whatever } 
    format.any { whatever } 
    end 
end 

basta usare:

def some_action 
    ... 
end 

e Rails sarà di default per cercare some_action.html.erb o qualsiasi altro formato è stato richiesto. Se non si definiscono viste diverse da html, tutti gli altri formati non riusciranno se richiesto.

+0

Penso che voglia abbandonare anche il formato: dalle rotte –

5

Poiché Rails utilizza l'equivalente di un carattere jolly per gestire i formati ".: Format" è un po 'più difficile impedire le cose sul lato del percorso.

Invece di questo, è piuttosto semplice catturare richieste non HTML in un filtro precedente. Ecco un modo questo potrebbe sembrare:

class ApplicationController < ActionController::Base 
    before_filter :check_format 

    private 

    def check_format 
     if request.format != Mime::HTML 
     raise ActionController::RoutingError, "Format #{params[:format].inspect} not supported for #{request.path.inspect}" 
     end 
    end 

end 

ActionController :: RoutingErrors vengono gestiti come errori 404 che è sensibile. Nel caso in cui si ha un'azione che deve sostenere qualcosa di diverso da HTML, basta usare:

skip_before_filter :check_format, :only => ACTION_NAME 
6

è necessario includere quelle rotte in un ambito, se si desidera limitare loro di un formato specifico (ad esempio html o JSON). I vincoli purtroppo non funzionano come previsto in questo caso.

Questo è un esempio di un blocco di questo tipo ...

scope :format => true, :constraints => { :format => 'json' } do 
    get '/bar' => "bar#index_with_json" 
end 

Maggiori informazioni possono essere trovate qui: https://github.com/rails/rails/issues/5548

Questa risposta è copiato dalla mia precedente risposta qui ..

Rails Routes - Limiting the available formats for a resource

Problemi correlati