Je suis en train de convertir une application Rails 2 en Rails 3. J'ai actuellement un contrôleur configuré comme suit:
class Api::RegionsController < ApplicationController
respond_to :xml, :json
end
avec et une action qui ressemble à ce qui suit:
def index
@regions = Region.all
respond_with @regions
end
L'implémentation est assez simple, api/regions, api/regions.xml et api/regions.json répondent toutes comme vous le souhaitiez. Le problème est que je veux que les API/régions répondent par défaut via XML. Certains consommateurs attendent une réponse XML et je n’aimerais pas qu’ils modifient toutes leurs URL afin d’inclure le fichier .xml, sauf si cela est absolument nécessaire.
Dans Rails 2, vous obtiendriez cela en procédant comme suit:
respond_to do |format|
format.xml { render :xml => @region.to_xml }
format.json { render :json => @region.to_json }
end
Mais dans Rails 3, je ne trouve pas le moyen de le remplacer par une réponse XML. Des idées?
Si je comprends ce que vous essayez de faire, vous pouvez probablement résoudre le problème en définissant le format de ressource par défaut sur XML. Cela permettra à vos utilisateurs de faire des demandes en utilisant 'api/regions' et d'avoir la réponse par défaut à XML. Examinez les sections "Routage des espaces de noms de contrôleurs" et "Définition des valeurs par défaut" à l'adresse:
http://guides.rubyonrails.org/routing.html
Vous pouvez faire quelque chose comme ceci dans le fichier routes.rb:
namespace "api" do
resources :regions, :defaults => { :format => 'xml' }
end
Ensuite, vous devriez pouvoir avoir le travail suivant pour vos méthodes de contrôleur:
class Api::RegionsController < ApplicationController
respond_to :xml, :json
def index
respond_with(@regions = Region.all)
end
end
Je me bats ce problème aujourd'hui et je me suis installé pour la solution before_filter
que vous avez vous-même mentionnée dans votre commentaire:
before_filter :default_format_xml
# Set format to xml unless client requires a specific format
# Works on Rails 3.0.9
def default_format_xml
request.format = "xml" unless params[:format]
end
Cette solution permet également de prendre en compte la négociation de contenu, ce qui était un facteur dans mon cas. Je voulais que les navigateurs Web obtiennent une vue HTML mais que les clients personnalisés (sans en-têtes Accept) obtiennent JSON. Cela a résolu mon problème:
before_filter :default_format_json
def default_format_json
if(request.headers["HTTP_ACCEPT"].nil? &&
params[:format].nil?)
request.format = "json"
end
end
Ce n'est pas ce que vous cherchez, mais ce que vous souhaitez:
def index
@regions = Region.all
respond_to do |format|
format.json { render :json => @regions }
format.any(:xml, :html) { render :xml => @regions }
end
end
"Répondre à vous permet également de spécifier un bloc commun pour différents formats en utilisant n'importe quel"
Eh bien, comme vous avez noté que chaque format devrait être explicitement rendu avec un appel de rendu spécifique, vous pouvez également éviter toute demande avec un format inconnu ou non pris en charge, pour mon exemple appelé default , comme suit:
rescue_from ActionController::UnknownFormat, with: ->{ render nothing: true }
Vous pouvez simuler l'appel au format inconnu avec la ligne de navigateur simple (exmp.firefox) (en mode développement):
http://localhost/index.default
Il appellera la méthode :index
d'un contrôleur racine au format appelé default .