web-dev-qa-db-ja.com

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

Railsメソッドでrespond_withメソッドがいかにクールであるかを何度も読んでいます。しかし、Rails APIでも、検索しても、参照が見つかりません。起源。誰が私にそれがどのように機能するか(どのオプションを使用できるかなど)説明したり、実際に実装されている場所を教えて自分でコードを閲覧したりできますか?

121
jaydel

Rails 4.2+の更新

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

#respond_toインスタンスメソッド、は、しかし、まだRailsの一部です(この記事の執筆時点で5.2rc1 )。

ActionController::MimeResponds の公式Rails AP​​Iドキュメントでは、#respond_toの仕組みについて説明しています。 #respond_withおよび::respond_toの元のRails Guidesドキュメントコメントは、まだ responders gemソースコード にあります。


元の回答

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


デフォルトでは、応答でRailsが提供する唯一の動作は、アクションに一致する名前でテンプレートをレンダリングする暗黙の試行です。それ以上のことを行うには、アクション内でより多くの指示が必要です。または、複数の形式の応答を処理するブロックを含むカスタムの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つの方法は、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

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

インスタンスレベル:respond_with

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

別の方法として、 responders gemは、デフォルトの動作の一部をオーバーライドするためのモジュールを提供するだけではありません。デフォルトレスポンダーを拡張する匿名クラスでデフォルトレスポンダーをオーバーライドし、カスタムモジュールをこのクラスに混合するためのクラスレベルのメソッドを提供します。ここで最も有用なのはフラッシュレスポンダーで、これはデフォルトのフラッシュセットを提供し、カスタマイズをI18nシステム(デフォルトではconfig/locales/en.yml)に委任します。

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

123
Cluster