Rails respond_with: comment ça marche?

128

J'ai lu ici et là à quel point la respond_withméthode est cool dans Rails 3. Mais je ne peux même pas en trouver une référence dans les API Rails ou en recherchant la source. Quelqu'un peut-il m'expliquer comment cela fonctionne (quelles options vous pouvez utiliser, etc.) ou me diriger vers l'endroit où il est réellement implémenté afin que je puisse parcourir le code par moi-même?

Jaydel
la source

Réponses:

128

Mise à jour pour Rails 4.2+

#respond_withet ::respond_to( méthode de classe nb ) ne font plus partie de Rails . Ils ont été migrés vers le joyau des répondeurs tiers à partir de Rails 4.2 ( notes de publication / validation datées d'août 2014). Bien que les répondeurs ne soient pas inclus dans Rails par défaut, il s'agit d'une dépendance de Devise, et donc disponible dans de nombreuses applications Rails.

La #respond_to méthode d'instance, cependant, fait toujours partie de Rails (5.2rc1 à ce jour).

La documentation officielle de l'API Rails pour ActionController::MimeRespondsexplique comment #respond_tofonctionne. La documentation originale des guides Rails commente #respond_withet ::respond_topeut toujours être trouvée dans le code source de la gemme des répondeurs .


Réponse originale

Le code des répondeurs est basé sur une classe et un module. MimeResponds qui est inclus dans ActionController :: Base , la classe dont vous ApplicationControllerhéritez. Ensuite, il y a ActionController :: Responder qui fournit le comportement par défaut lors de l'utilisation de respond_with.


Par défaut, le seul comportement que les rails fournissent dans la réponse est une tentative implicite de rendu d'un modèle avec un nom correspondant à l'action. Tout ce qui va au-delà de cela nécessite plus d'instructions dans l'action, ou un appel respond_to personnalisé avec un bloc pour gérer plusieurs réponses de format.

Comme la plupart des contrôleurs utilisent un modèle de personnalisation assez courant, les répondeurs fournissent un niveau supplémentaire d'abstraction en introduisant plus de comportement par défaut. Lisez les actions appelant to_xml / to_json pour des formats spécifiques, et les actions de mutateur fournissant la même chose ainsi que des redirections pour les actions de mutateur réussies.


Il existe quelques possibilités de personnaliser le comportement des intervenants, des ajustements subtils au remplacement ou à l'extension complète du comportement.

Niveau de classe: respond_to

Ici, vous spécifiez les formats que le répondeur doit gérer. Les formats peuvent être personnalisés en fonction des actions auxquelles ils s'appliqueront. Chaque format peut être spécifié avec des appels séparés, permettant une personnalisation complète des actions pour chaque format.

# Responds to html and json on all actions
respond_to :html, :json

# Responds to html and json on index and show actions only.
respond_to :html, :json, :only => [:index,:show]

# Responds to html for everything except show, and json only for index, create and update
respond_to :html, :except => [:show]
respond_to :json, :only => [:index, :create, :update]

Niveau de classe: responder

Il s'agit d'un attribut de classe qui contient le répondeur. Cela peut être tout ce qui répond à un appel, ce qui signifie que vous pouvez utiliser un proc / lambda ou une classe qui répond à un appel. Une autre alternative consiste à mélanger un ou plusieurs modules au répondeur existant pour surcharger les méthodes existantes, augmentant ainsi le comportement par défaut.

class SomeController < ApplicationController
  respond_to :json

  self.responder = proc do |controller, resources, options|
    resource = resources.last
    request = controller.request
    if request.get?
      controller.render json: resource
    elsif request.post? or request.put?
      if resource.errors.any?
        render json: {:status => 'failed', :errors => resource.errors}
      else
        render json: {:status => 'created', :object => resource}
      end
    end
  end
end

Bien qu'il puisse y avoir des cas d'utilisation de bord intéressants, il est plus probable que l'extension ou le mélange de modules dans le répondeur par défaut soit des modèles plus courants. Dans tous les cas, les options qui sont pertinentes sont les ressources et les options, car elles sont transmises par le from respond_with.

Niveau d'instance: respond_with

Les options ici sont celles qui seraient passées pour render ou redirect_to dans votre contrôleur, mais elles ne sont incluses que pour les scénarios de réussite. Pour les actions GET, ce sont les appels de rendu, pour les autres actions, ce sont les options de redirection. La plus utile d'entre elles est probablement l' :locationoption, qui peut être utilisée pour remplacer ce chemin de redirection au cas où les arguments pour respond_with ne seraient pas suffisants pour construire la bonne URL.

# These two are essentially equal
respond_with(:admin, @user, @post)
respond_with(@post, :location => admin_user_post(@user, @post)

# Respond with a 201 instead of a 200 HTTP status code, and also
# redirect to the collection path instead of the resource path
respond_with(@post, :status => :created, :location => posts_path)

# Note that if you want to pass a URL with a query string
# then the location option would be needed.
# /users?scope=active
respond_with(@user, :location => users_path(:scope => 'active'))

En guise d'alternative, le gem responders ne fournit pas seulement certains modules pour remplacer certains des comportements par défaut. Il remplace le répondeur par défaut par une classe anonyme qui étend le répondeur par défaut et fournit une méthode au niveau de la classe pour mélanger des modules personnalisés à cette classe. Le plus utile ici est le répondeur flash, qui fournit un ensemble de flashs par défaut, déléguant la personnalisation au système I18n, config/locales/en.ymlpar défaut.

Certains exemples de répondeurs personnalisés que j'ai utilisés dans des projets précédents incluent un répondeur qui décorait automatiquement mes ressources et fournissait un ensemble par défaut de titres de page avec une interface pour personnaliser ou remplacer facilement le titre de la page.

Grappe
la source
1
Je pense que vous voulez dire (dans le corps de la classe) self.responder =comme responder =l'attribuera juste à un local
horseyguy
Je vous remercie! L'existence de l' locationoption était l'information dont j'avais besoin!
JellicleCat
1
Cette explication est-elle toujours pertinente pour Rails 4/5? J'ai entendu dire que ce respond_withserait obsolète, mais je n'arrive pas à comprendre pourquoi.
Arnlen
1
@Arnlen, respond_with a été extrait en tant que `` répondeurs ' ' de gemmes séparés
Nick Roz
Notez que pour que vos flashs config/locales/en.ymlfonctionnent, vous devez responders :flashen haut de votre contrôleur.
bjnord