Railsのrespond_with:どのように機能しますか?


128

respond_withRails 3でのメソッドのクールさについては、あちこちで読んでいますが、Rails APIでも、ソースを検索しても、その参照を見つけることができません。誰かが私にそれがどのように機能するか(使用できるオプションなど)を説明したり、実際に実装されている場所を指摘して自分でコードを熟読したりできますか?

回答:


128

Rails 4.2以降のアップデート

#respond_withそして、::respond_toNBクラスメソッド)ではない、もはやレールの一部。それらはRails 4.2の時点でサードパーティのレスポンダー gemに移行されました(リリースノート / コミットは2014年8月)。レスポンダはデフォルトではRailsに含まれていませんが、Deviseの依存関係であるため、多くのRailsアプリケーションで使用できます。

#respond_to インスタンスメソッドは、しかし、ある静止レールの一部(これを書いているよう5.2rc1)。

の公式Rails APIドキュメントで、ActionController::MimeRespondsその#respond_to仕組みを説明しています。元Railsのガイドのドキュメントは、コメント#respond_with::respond_toまだで見つけることができます応答の宝石のソースコード


元の回答

レスポンダのコードは、クラスとモジュールに基づいています。継承元のクラスであるActionController :: Baseに含まれるMimeResponds。次に、respond_withを使用するときにデフォルトの動作を提供するActionController :: Responderがあります。ApplicationController


デフォルトでは、応答で提供される動作レールは、アクションと一致する名前でテンプレートをレンダリングする暗黙の試みのみです。それ以上のことは、アクション内のより多くの指示、または複数のフォーマット応答を処理するためのブロックを伴うカスタムのrespond_to呼び出しを必要とします。

ほとんどのコントローラーはかなり一般的なカスタマイズのパターンを使用するため、レスポンダーはより多くのデフォルトの動作を導入することにより、追加レベルの抽象化を提供します。特定の形式のto_xml / to_jsonを呼び出すアクションと、同じものを提供するミューテーターアクションと、成功したミューテーターアクションのリダイレクトを読み取ります。


微妙な調整から、動作の完全なオーバーライドまたは拡張まで、レスポンダの動作をカスタマイズする機会がいくつかあります。

クラスレベル: respond_to

ここでは、レスポンダが処理するフォーマットを指定します。適用するアクションについて、フォーマットをカスタマイズできます。各フォーマットは個別の呼び出しで指定できるため、各フォーマットのアクションを完全にカスタマイズできます。

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

クラスレベル: responder

これはレスポンダを保持するクラス属性です。これは、呼び出しに応答するものであれば何でもかまいません。つまり、呼び出しに応答するproc / lambdaまたはクラスを使用できます。別の方法としては、1つまたは複数のモジュールを既存のレスポンダにミックスインして、既存のメソッドをオーバーロードし、デフォルトの動作を強化する方法があります。

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

いくつかの興味深いエッジのユースケースがあるかもしれませんが、デフォルトのレスポンダーにモジュールを拡張または混合することは、より一般的なパターンになる可能性が高いです。いずれの場合も、respond_withから渡されるので、関連するオプションはリソースとオプションです。

インスタンスレベル: respond_with

ここでのオプションは、コントローラでrenderまたはredirect_toに渡されるオプションですが、成功シナリオでのみ含まれています。GETアクションの場合、これらはレンダーコールになります。他のアクションの場合、これはリダイレクトのオプションになります。おそらくこれらの中で最も役立つのは:locationオプションです。response_withの引数が適切な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'))

代替手段として、レスポンダー gemは、デフォルトの動作の一部をオーバーライドするためのいくつかのモジュールを提供するだけではありません。デフォルトのレスポンダを拡張する匿名クラスでデフォルトのレスポンダをオーバーライドし、カスタムクラスをこのクラスにミキシングするためのクラスレベルのメソッドを提供します。ここで最も役立つのは、デフォルトでフラッシュのセットを提供し、カスタマイズをI18nシステムに委任するフラッシュレスポンダーconfig/locales/en.ymlです。

以前のプロジェクトで使用したカスタムレスポンダーの例には、リソースを自動的に装飾し、ページタイトルのデフォルトセットを提供し、ページタイトルを簡単にカスタマイズまたはオーバーライドするためのインターフェイスが含まれています。


1
ローカルクラスに割り当てられるのself.responder =と同じように(クラスの本文では)と思いますresponder =
horseyguy 2014

ありがとうございました!locationオプションの存在は私が必要とした情報でした!
JellicleCat

1
その説明はまだRails 4/5に関連していますか?それrespond_withが廃止されると聞いていましたが、どうしてかわかりません。
Arnlen

1
@ Arnlen、respond_withは個別の宝石「レスポンダー」として抽出されました
Nick Roz

のフラッシュが機能するconfig/locales/en.ymlresponders :flashは、コントローラーの上部に必要です。
bjnord 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.