2009-11-04 5 views
12

J'ai un site Rails 2.1.2 qui n'a que des modèles html, par ex. jobs.html.erb, quand je demande une ressource reposante:Méthodes pour limiter le format de rendu Rails à html

www.mysite.com/jobs/1

Il rend mon travail en html, cependant, si je demande:

www.mysite.com/jobs/1.xml

Je reçois l'erreur:

Template is missing Missing template jobs/show.xml.erb in view path c:/workspace/mysite/app/views

ce qui est pire est que je peux aussi demander quelque chose comme

www.mysite.com/jobs/1.xyz

Et en effet, je vois l'erreur:

Template is missing Missing template jobs/show.xyz.erb in view path c:/workspace/mysite/app/views

Pour stricly contenu actuel juste html, ce qui est la manière la plus propre et la plus simple de dire Rails que je ne veux pas rendre quelque chose autre que les fichiers .html.erb.

Il est important de noter que:

  • Certains de mes actions de contrôleur contiennent des appels conditionnels à la méthode render() tandis que d'autres utilisent le comportement par défaut de Rails-à-dire si vous n'appelez pas render(), la Le modèle nommé youraction.html.erb sera rendu.
  • Mon code ne pas utiliser la méthode

responds_to() Ce serait formidable si la solution n'a pas été à la rendre/niveau responds_to que je dois modifier un nombre important d'actions. Peut-être existe-t-il un moyen de configurer Rails pour que seuls les templates html soient rendus?

Répondre

7

Si vous ne souhaitez pas utiliser responds_to, vous pouvez le faire:

class ApplicationController < ActionController::Base 
    before_filter :allow_only_html_requests 

    ... 

    def allow_only_html_requests 
    if params[:format] && params[:format] != "html" 
     render :file => "#{RAILS_ROOT}/public/404.html" 
    end 
    end 

    ... 

end 

Cela fonctionnera avant toutes les demandes et seulement que ceux qui ne spécifient pas le format du tout, ou spécifier le format html par . Tous les autres obtiennent 404'd. Vous pouvez créer un public/406.html si vous voulez retourner 406 inacceptable.

+1

Cela ne renvoie pas réellement un 404, cependant, il rend juste '404.html' comme réponse 200. Vous devrez ajouter ': status => 404' (ou': status =>: not_found'). De même, pour un 406, vous devrez utiliser ': status => 406' (ou': status =>: not_acceptable'). – Peeja

+1

Cela échoue également si la demande utilise l'en-tête 'accept' pour demander le type de réponse, car cela n'est pas stocké dans les paramètres – zimkies

14

Dans vos itinéraires, vous pouvez simplement supprimer la ligne:

map.connect ':controller/:action/:id.:format' 

Et le « xyz » ne sera plus être routé, entraînant des erreurs 404 /.

+0

La suppression de cette ligne ne résout pas le problème dans Rails 3.2.6: il est déjà commenté mais l'erreur Modèle manquant apparaît toujours. – collimarco

5

La solution de Ben fonctionne.

Considérons la réponse à la solution, cependant. C'est plus propre car cela permet une flexibilité lorsque vous aurez inévitablement besoin d'ouvrir une action pour un appel json ou xml JavaScript. Alors vous n'aurez pas à ajouter

skip_before_filter :allow_only_html_requests, :only => [:show] 

J'aime personnellement le respond_to block; c'est très descriptif.

respond_to do |wants| 
    wants.html 
end 

Tout format non spécifié dans le bloc sera automatiquement provoquer un HTTP 406 Non acceptable à retourner. C'est bien.

+1

D'accord. Le bloc responds_to ouvre un monde de flexibilité, et si vous pouvez prendre le temps d'en ajouter un pour .html à chacune de vos actions de contrôleurs, c'est une solution bien plus avant-gardiste. – Ben

10

Vous pouvez utiliser la fonctionnalité Rails par action. Qu'est-ce que c'est ça? -> Il est également possible de remplacer la gestion des ressources standard en passant dans un bloc à respond_with spécifier quels formats pour passer outre pour cette action:

class UsersController < ApplicationController::Base 

    respond_to :html, :xml, :json 

    # Override html format since we want to redirect to a different page, 
    # not just serve back the new resource 
    def create 
    @user = User.create(params[:user]) 
    respond_with(@user) do |format| 
     format.html { redirect_to users_path } 
    end 
    end 
end 

: sauf Et: seules options

Vous pouvez également passer dans: sauf et: seules options aux formats de support uniquement pour des actions spécifiques (comme vous le faites avec before_filter):

class UsersController < ApplicationController::Base 
    respond_to :html, :only => :index 
    respond_to :xml, :json, :except => :show 
    ... 
end 

Le: tout Format

Si vous êtes souhaitez toujours utiliser respond_to au sein de vos actions individuelles, utilisez le: tout format de ressource qui peut être utilisé comme un caractère générique correspondant contre tous les formats non spécifiés:

class UsersController < ApplicationController::Base 

    def index 

    @users = User.all 

    respond_to do |format| 
     format.html 
     format.any(:xml, :json) { render request.format.to_sym => @users } 
    end 
    end 
end 
+1

Rails 3 uniquement. – Jared

+0

Jared, pourriez-vous s'il vous plaît être plus précis qui des trois options est Rails 3 seulement! Je cours sur Rails 2.3.4 et le: any Option fonctionne. – leviathan

1

Je recevais non sensical demandes de format d'image sur les fichiers HTML, déclenchant un 500 avec MissingTemplate. Je suit à édictées à la fin de mon action:

def show 
    # [...] 
    respond_to :html 
end 

Et maintenant, au lieu d'obtenir des rapports d'erreur, nous émettons 406 à ce demandeur mischievious.