2009-09-03 8 views
13

Lors du routage des ressources dans Rails, l'attribut de format facultatif est automatiquement ajouté aux routes générées. Ceci afin que la ressource en question puisse être demandée en XML, HTML, etc. Les formats réellement autorisés sont généralement décrits dans le contrôleur en utilisant respond_to.Comment limiter les formats de ressources dans le fichier des itinéraires Rails

Cependant, dans la plupart des cas, vous ne voulez prendre en charge que le format HTML et vous avez l'impression d'écrire respond_to :html dans chaque action de chaque contrôleur. Il serait donc cool s'il existe un moyen de limiter les types de contenu autorisés lors de la construction des routes dans le fichier routes.rb, par ex.

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

Existe-t-il un moyen d'y parvenir soit natif, soit via un plugin?

P.S. La manière habituelle de contourner ce problème consiste simplement à ignorer le problème et à ne pas utiliser respond_to dans les actions. Mais cela ne limite en réalité pas les types de contenu autorisés. Au lieu de cela, il s'attend simplement à ce qu'un modèle existe dans le répertoire views pour chaque type de contenu possible. Si l'un n'existe pas à la demande, le système lancera une erreur HTTP 500.

Répondre

1

Dans les deux cas, ne voulez-vous pas une erreur HTTP 500? Comme dans la deuxième ligne de votre exemple, si quelqu'un a demandé JSON au lieu de HTML ou XML n'est pas un code d'erreur renvoie la réponse appropriée?

+1

Non, une erreur 500 signifie quelque chose a mal tourné sur le serveur . Si un type de contenu n'est pas pris en charge, il ne s'agit pas d'une erreur de serveur: il s'agit d'une erreur client (le client ne devrait pas l'avoir demandé). Un 406 serait le code de réponse correct. Voir "Codes de réponse HTTP": http://www.sitepoint.com/blogs/2008/02/04/restful-rails-part-i/ –

+0

Sûrement si vous allez marquer .xml ou .html à la fin de l'URL et ce format n'est pas supporté alors vous devriez retourner 404 non trouvé. Il semble un peu effronté d'ignorer l'utilisation de conneg en créant des URL pour chaque type de contenu, mais ensuite voler le code de réponse pour quand il n'y a pas de type de contenu valide dans l'en-tête accepter! –

+0

Eh bien, vous pourriez avoir un point - même si c'est en fait comment Rails fonctionne hors de la boîte. Mais néanmoins ce n'est pas le point de ma question. Je voudrais toujours spécifier cela dans un emplacement central (de préférence le fichier de routes) - peu importe si puis un 404 ou un 406 est retourné sur erreur –

3

Je crois que vous êtes capable de faire quelque chose comme ceci:

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

Si l'utilisateur demande html ou JSON ça va le faire comme il se doit, mais toute autre chose rendre le texte « Format non valide ».

+0

ça marcherait mais je pense qu'il veut laisser tomber: le format des routes –

0

plutôt que de faire:

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

il suffit d'utiliser:

def some_action 
    ... 
end 

et Rails par défaut à la recherche de some_action.html.erb ou tout autre format a été demandé. Si vous ne définissez aucune vue autre que html, tous les autres formats échoueront si demandé.

+0

Je pense qu'il veut aussi supprimer le: format des routes –

5

Étant donné que Rails utilise l'équivalent d'un caractère générique pour gérer les formats «.: Format», il est un peu plus difficile d'empêcher les choses du côté de la route. Au lieu de cela, il est assez facile d'attraper toutes les demandes non HTML dans un filtre avant. Voici une façon dont cela pourrait ressembler:

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 sont traitées comme des erreurs 404 qui est sensible. Dans le cas où vous avez une action qui doit prendre en charge quelque chose d'autre que le HTML, il suffit d'utiliser:

skip_before_filter :check_format, :only => ACTION_NAME 
6

Vous devez envelopper ces routes dans un champ si vous voulez les limiter à un format spécifique (par exemple html ou json). Les contraintes ne fonctionnent malheureusement pas comme prévu dans ce cas.

Ceci est un exemple d'un tel bloc ...

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

Plus d'informations peuvent être trouvées ici: https://github.com/rails/rails/issues/5548

Cette réponse est copiée de ma précédente réponse ici ..

Rails Routes - Limiting the available formats for a resource

Questions connexes