Rails reply_with: Wie funktioniert es?

128

Ich habe hier und da gelesen, wie cool die respond_withMethode in Rails 3 ist. Aber ich kann weder in den Rails-APIs noch durch Durchsuchen der Quelle einen Verweis darauf finden. Kann mir jemand erklären, wie es funktioniert (welche Optionen Sie verwenden können usw.) oder mich auf den Ort verweisen, an dem es tatsächlich implementiert ist, damit ich den Code selbst lesen kann?

Jaydel
quelle

Antworten:

128

Update für Rails 4.2+

#respond_withund ::respond_to( nb class method) sind nicht mehr Teil von Rails . Sie wurden ab Rails 4.2 in das Juwel der Responder von Drittanbietern migriert ( Versionshinweise / Commit vom August 2014). Während Responder standardmäßig nicht in Rails enthalten sind, ist dies eine Abhängigkeit von Devise und daher in vielen Rails-Anwendungen verfügbar.

Die #respond_to Instanzmethode ist jedoch immer noch Teil von Rails (5.2rc1 zum Zeitpunkt dieses Schreibens).

In der offiziellen Rails API-Dokumentation wird ActionController::MimeRespondserläutert, wie dies #respond_tofunktioniert. Die originalen Rails Guides-Dokumentationskommentare für #respond_withund ::respond_tofinden sich immer noch im Quellcode des Responders Gem .


Ursprüngliche Antwort

Der Code für die Responder basiert auf einer Klasse und einem Modul. MimeResponds, das in ActionController :: Base enthalten ist , der Klasse, von der Sie ApplicationControllererben. Dann gibt es ActionController :: Responder, der das Standardverhalten bei Verwendung von reply_with bereitstellt.


Standardmäßig ist das einzige Verhalten, das Rails in der Antwort bereitstellt, ein impliziter Versuch, eine Vorlage mit einem Namen zu rendern, der der Aktion entspricht. Alles darüber hinaus erfordert mehr Anweisungen innerhalb der Aktion oder einen benutzerdefinierten reply_to-Aufruf mit einem Block, um Antworten mit mehreren Formaten zu verarbeiten.

Da die meisten Controller ein recht häufiges Anpassungsmuster verwenden, bieten Responder eine zusätzliche Abstraktionsebene, indem sie mehr Standardverhalten einführen. Lesen Sie Aktionen, die to_xml / to_json für bestimmte Formate aufrufen, und Mutator-Aktionen, die dieselben bereitstellen, sowie Weiterleitungen für erfolgreiche Mutator-Aktionen.


Es gibt einige Möglichkeiten, das Verhalten von Respondern anzupassen, von subtilen Änderungen bis hin zum vollständigen Überschreiben oder Erweitern des Verhaltens.

Klassenstufe: respond_to

Hier geben Sie die Formate an, die der Responder verarbeiten soll. Die Formate können angepasst werden, auf welche Aktionen sie angewendet werden. Jedes Format kann mit separaten Aufrufen angegeben werden, sodass die Aktionen für jedes Format vollständig angepasst werden können.

# 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]

Klassenstufe: responder

Dies ist ein Klassenattribut, das den Responder enthält. Dies kann alles sein, was auf einen Anruf reagiert. Dies bedeutet, dass Sie einen proc / lambda oder eine Klasse verwenden können, die auf einen Anruf reagiert. Eine andere Alternative besteht darin, ein oder mehrere Module mit dem vorhandenen Responder zu mischen, um vorhandene Methoden zu überladen und das Standardverhalten zu verbessern.

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

Obwohl es einige interessante Edge-Anwendungsfälle geben kann, ist es wahrscheinlicher, dass das Erweitern oder Mischen von Modulen in den Standard-Responder häufiger vorkommt. In jedem Fall sind die relevanten Optionen die Ressourcen und Optionen, wie sie von from reply_with durchlaufen werden.

Instanzstufe: respond_with

Die hier aufgeführten Optionen werden an render oder redirect_to in Ihrem Controller übergeben, sind jedoch nur für Erfolgsszenarien enthalten. Bei GET-Aktionen sind dies die Renderaufrufe, bei anderen Aktionen die Optionen für die Umleitung. Die wahrscheinlich nützlichste davon ist die :locationOption, mit der dieser Umleitungspfad überschrieben werden kann, falls die Argumente für reply_with nicht ausreichen, um die richtige URL zu erstellen.

# 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'))

Alternativ bietet das Responder- Gem nicht nur einige Module zum Überschreiben einiger Standardverhalten. Es überschreibt den Standard-Responder mit einer anonymen Klasse, die den Standard-Responder erweitert, und bietet eine Methode auf Klassenebene zum Einmischen benutzerdefinierter Module in diese Klasse. Am nützlichsten ist hier der Flash-Responder, der einen Standardsatz von Flashs bereitstellt und die Anpassung an das I18n-System delegiert.config/locales/en.yml standardmäßig .

Einige Beispiele für benutzerdefinierte Responder, die ich in früheren Projekten verwendet habe, umfassen einen Responder, der meine Ressourcen automatisch dekoriert und einen Standardsatz von Seitentiteln mit einer Oberfläche zum einfachen Anpassen oder Überschreiben des Seitentitels bereitstellt.

Cluster
quelle
1
Ich denke, Sie meinen (in der Klasse), self.responder =wie gerade responder =einem lokalen
horseyguy
Danke dir! Das Vorhandensein der locationOption war die Information, die ich brauchte!
JellicleCat
1
Ist diese Erklärung für Rails 4/5 noch relevant? Ich habe gehört, dass respond_withdas veraltet wäre, aber ich kann nicht herausfinden, warum.
Arnlen
1
@Arnlen, reply_with wurde als separater Edelstein ' Responder ' extrahiert
Nick Roz
Beachten Sie, dass Sie Blitze in Ihrem Controller oben auf Ihrem Controller config/locales/en.ymlbenötigen, damit sie funktionieren responders :flash.
Bjnord