2009-09-03 8 views
13

Al enrutar recursos en Rails, el atributo de formato opcional se agrega automáticamente a las rutas generadas. Esto es para que el recurso en cuestión se pueda solicitar como XML, HTML, etc. Los formatos que realmente se permiten generalmente se describen en el controlador usando respond_to.Cómo limitar los formatos de recursos en el archivo de rutas de Rails

Pero en muchos casos solo desea admitir HTML y se siente como una sobrecarga escribir respond_to :html en cada acción en cada controlador. Por lo tanto, sería fantástico si ya existiera una forma de limitar los tipos de contenido permitidos al construir las rutas en el archivo routes.rb, p.

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

¿Hay alguna manera de lograr esto ya sea nativo o mediante un complemento?

P.S. La forma habitual de evitar esto es simplemente ignorar el problema y no usar respond_to en las acciones. Pero esto en realidad no limita los tipos de contenido permitidos. En su lugar, solo espera que exista una plantilla en el directorio de vistas para cada tipo de contenido posible. Si no existe uno cuando se solicita, el sistema lanzará un error HTTP 500.

Respuesta

1

En cualquier caso, ¿no le gustaría un error HTTP 500? Al igual que en la segunda línea de su ejemplo, si alguien solicitó JSON en lugar de HTML o XML no es un código de error, ¿devuelve la respuesta adecuada?

+1

No, un error 500 significa que algo salió mal en el servidor . Si no se admite un tipo de contenido, no se trata de un error del servidor; es un error del cliente (el cliente no debería haberlo solicitado). Un 406 sería el código de respuesta correcto. Consulte "Códigos de respuesta HTTP": http://www.sitepoint.com/blogs/2008/02/04/restful-rails-part-i/ –

+0

Seguramente si va a etiquetar .xml o .html al final de la URL y ese formato no son compatibles, entonces debe devolver 404 no encontrado. ¡Parece descarado ignorar el uso de conneg al crear URL para cada tipo de contenido, pero luego robar el código de respuesta para cuando no haya un tipo de contenido válido en el encabezado accept! –

+0

Bueno, quizás tengas razón, a pesar de que así es como Rails funciona de la caja. Pero, sin embargo, este no es el punto de mi pregunta. Todavía me gustaría especificar esto en una ubicación central (preferiblemente el archivo de rutas), sin importar si se devuelve un 404 o un 406 en el error –

3

creo que son capaces de hacer algo como esto:

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

Si el usuario solicita HTML o JSON que lo hará como debe ser, pero nada más va a hacer que el texto "Formato no válido".

+0

que funcionaría, pero creo que quiere soltar el: formato de las rutas –

0

en lugar de hacerlo:

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

sólo tiene que utilizar:

def some_action 
    ... 
end 

y Rails por defecto en busca de some_action.html.erb o cualquier formato fue solicitada. Si no define ninguna vista que no sea html, todos los demás formatos fallarán si se solicita.

+0

Creo que también quiere eliminar el formato de las rutas –

5

Dado que Rails usa el equivalente de un comodín para manejar formatos ".: Formato", es un poco más difícil evitar cosas en el lado de la ruta.

En lugar de esto, es una manera bastante fácil de detectar cualquier solicitud que no sea HTML en un filtro anterior. He aquí una manera de esta situación:

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 se manejan como errores 404 que es sensible. En el caso de que usted tiene una acción que tiene que apoyar algo que no sea HTML, sólo tiene que utilizar:

skip_before_filter :check_format, :only => ACTION_NAME 
6

Debe envolver esas rutas en un ámbito si desea restringir a un formato específico (por ejemplo, html o json). Restricciones desafortunadamente no funcionan como se esperaba en este caso.

Este es un ejemplo de dicho bloque ...

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

Más información se puede encontrar aquí: https://github.com/rails/rails/issues/5548

Esta respuesta se copia de mi respuesta anterior aquí ..

Rails Routes - Limiting the available formats for a resource

Cuestiones relacionadas