57 votes

Rails 3 respond_to : format par défaut ?

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

La mise en œuvre est assez simple, api/regions, api/regions.xml et api/regions.json répondent tous comme prévu. Le problème est que je veux que les api/regions répondent par défaut via XML. J'ai des consommateurs qui attendent une réponse XML et je ne voudrais pas qu'ils modifient toutes leurs URL pour inclure .xml, sauf en cas de nécessité absolue.

Dans Rails 2, vous pouvez accomplir cela en faisant ceci :

respond_to do |format|
  format.xml { render :xml => @region.to_xml }
  format.json { render :json => @region.to_json }
end

Mais dans Rails 3, je n'arrive pas à trouver un moyen de le transformer en réponse XML par défaut. Une idée ?

0 votes

Cet article de blog en parle : ryandaigle.com/articles/2009/8/10/ En particulier, regardez la section intitulée "Remplacement du comportement par défaut".

0 votes

Qu'en est-il de api/regions.html ? Doit-il rendre du HTML ? Ou bien... ?

0 votes

Aucun HTML ne doit être rendu par l'API. Les API sont séparées parce qu'un ensemble limité de fonctionnalités est disponible via l'API par rapport au site lui-même.

81voto

Mike Clymer Points 688

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 d'effectuer des requêtes en utilisant "api/regions" et d'obtenir une réponse en XML par défaut. Jetez un coup d'œil aux sections "Controller Namespaces and Routing" et "Defining Defaults" sur le site :

http://guides.rubyonrails.org/routing.html

Vous pourriez faire quelque chose comme ce qui suit dans routes.rb :

namespace "api" do
  resources :regions, :defaults => { :format => 'xml' }
end

Vous devriez alors être en mesure de faire fonctionner les méthodes suivantes pour vos contrôleurs :

class Api::RegionsController < ApplicationController
  respond_to :xml, :json

  def index 
    respond_with(@regions = Region.all)
  end
end

1 votes

Pour une raison quelconque, cela ne fonctionne pas pour moi. J'obtiens une erreur ActionController::UnknownFormat.

0 votes

À partir de la version 4.2 de Rails, vous devrez utiliser gem responder pour pouvoir utiliser respond_with. Vous pouvez en savoir plus sur répondre_avec ici .

49voto

clacke Points 1534

Je me suis battu contre cette question aujourd'hui, et je me suis contenté du before_filter solution 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 du 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ête Accept) obtiennent JSON. Cette solution 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

1 votes

Merci, c'est exactement ce que je cherchais !

1 votes

Merci. Cette approche est plus flexible que la définition du format dans les routes, car le format par défaut dans les routes écrasera Accept l'en-tête de toute façon.

30voto

Heikki Points 7416

Ce n'est pas ce que vous cherchez mais c'est lié :

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 à permet également de spécifier un bloc commun pour différents formats en utilisant n'importe quel"

0 votes

Merci, c'est vraiment utile de le savoir.

0voto

Eh bien, comme il a été noté que chaque format doit ê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é par défaut comme suit :

rescue_from ActionController::UnknownFormat, with: ->{ render nothing: true }

Vous pouvez simuler l'appel de format inconnu avec la ligne du navigateur simple (exmp.firefox) (en mode développement) :

http://localhost/index.default

Il appellera :index d'un contrôleur Root avec un format appelé par défaut .

-1voto

buru Points 2265

Une solution simple mais peu élégante consiste à remplacer le traitement du type de contenu html par un traitement du xml :

   respond_to :html, :xml, :json

   def index
      @regions = Region.all
      respond_with @regions do |format|
        format.html { render :xml => @regions }
      end
    end

0 votes

Merci, c'est similaire à la façon dont je le faisais dans Rails 2, mais j'espérais qu'il y avait un moyen de le faire sans le lister dans chaque action du contrôleur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X