web-dev-qa-db-fra.com

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

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?

56
bdorry

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
79
Mike Clymer

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
49
clacke

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"

29
Heikki

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 .

0