[解決済み] Rails respond_with:どのように機能するのですか?
質問
がいかにクールであるかということをあちこちで読んできました。
respond_with
メソッドがRails 3でいかにクールであるかということをあちこちで読んできました。しかし、RailsのAPIでもソースを検索しても、このメソッドへの参照すら見つけることができません。どなたか、このメソッドがどのように機能するか (使用できるオプションなど) を説明してくれるか、または実際に実装されている場所を教えてくれて、自分でコードを精査できるようになりませんか?
どのように解決するのですか?
Rails 4.2+に対応するためのアップデート
#respond_with
と
::respond_to
(
n.b.
クラスメソッド) は
はもはやRailsの一部ではありません
. これらはサードパーティの
レスポンダ
gemに移行されました (
リリースノート
/
コミット
2014年8月付け)。respondersはRailsにデフォルトで含まれていませんが、Deviseの依存関係にあるため、多くのRailsアプリケーションで利用可能です。
は
#respond_to
インスタンスメソッドです。
しかし、このメソッドは
はまだRailsの一部であり
(この記事を書いている時点では5.2rc1)です。
の公式Rails APIドキュメントは
ActionController::MimeResponds
の説明では、どのように
#respond_to
がどのように機能するかを説明しています。オリジナルのRails Guidesドキュメントのコメントでは
#respond_with
と
::respond_to
は、まだ
レスポンダジェムのソースコード
.
オリジナルの回答
レスポンダのコードはクラスとモジュールがベースになっています。
MimeResponds
に含まれている
ActionController::Base
に含まれるクラス、つまり
ApplicationController
から継承しているクラスです。次に
ActionController::Responder
があり、これは respond_with を使用した場合のデフォルトの動作を提供します。
デフォルトでは、railsがレスポンスで提供する唯一の動作は、アクションに一致する名前を持つテンプレートをレンダリングする暗黙の試みです。それ以上の動作は、アクション内でさらに指示を出すか、複数の形式のレスポンスを処理するためのブロックを持つカスタムresponder_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
面白いエッジユース・ケースもあるかもしれませんが、デフォルトのレスポンダにモジュールを拡張したり混ぜたりする方がより一般的なパターンになりそうです。いずれにせよ、関連するオプションはリソースとオプションであり、それらはfrom respond_withから渡されるからです。
インスタンスレベル
respond_with
ここでのオプションは、コントローラで render や redirect_to に渡されるものですが、これらは成功した場合のシナリオにのみ含まれています。GETアクションの場合はrenderの呼び出し、その他のアクションの場合はredirectのオプションになります。おそらくこれらのうち最も有用なのは
:location
オプションで、これは respond_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
をデフォルトで使用します。
私が以前のプロジェクトで使用したカスタム レスポンダーの例には、リソースを自動的に装飾するレスポンダーや、ページ タイトルを簡単にカスタマイズしたり上書きしたりするためのインターフェイスを備えたデフォルトのページ タイトル セットを提供するレスポンダーがあります。
関連
-
[解決済み] nil:NilClass の未定義メソッド `each' - しかし、なぜ?
-
[解決済み] Ruby: public static メソッドを作るには?
-
[解決済み] railsで':remote => true'はどのように動作するのでしょうか?
-
[解決済み] Ruby on Railsのデータベースをパージまたは再作成する
-
[解決済み] Ruby on Railsのマイグレーションでデータベースのカラムの名前を変更するにはどうすればよいですか?
-
[解決済み] Ruby on Railsで現在の絶対URLを取得するにはどうすればよいですか?
-
[解決済み] Rails DBの移行 - テーブルを削除するには?
-
[解決済み】Railsの認証トークンを理解する
-
[解決済み】Ruby on Railsはモデルのfield:typeを生成します - field:typeのオプションは何ですか?
-
[解決済み】強いパラメータを持つ配列を許可する方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Rails: sudo "コマンドが認識されないのはなぜですか?
-
[解決済み】コントローラでJSONをレンダリングする
-
[解決済み] 新規ユーザー作成時に ActiveModel::ForbiddenAttributesError が発生する。
-
[解決済み] Ruby on Railsのランナー
-
[解決済み] Rails のインストールに失敗する: activesupport には Ruby のバージョン >= 2.2.2 が必要です。
-
[解決済み] ウェブパッカーがアプリケーションを見つけ出せない
-
[解決済み] 変更欄のRailsマイグレーション
-
[解決済み] どなたか、collection_selectをわかりやすく説明していただけませんか?
-
[解決済み] Paramが無いか、値が空である。ParameterMissing in ResultsController#update
-
[解決済み] Railsコンソール:リロード!モデルファイルの変更が反映されない?考えられる理由は何でしょうか?