Rails respond_with:它是如何工作的?

我一直在这里和这里读到关于在respond_with方法有多酷。但是我甚至无法在Rails API中find对它的引用,或者通过search源代码find它。 任何人都可以向我解释它是如何工作的(你可以使用什么选项等),或者指向它实际实现的位置,以便我可以自己细读代码?

响应者的代码基于一个类和一个模块。 MimeResponds被包含在ActionController :: Base中 ,这是你的ApplicationControllerinheritance的类。 然后是ActionController :: Responder ,它提供了使用respond_with时的默认行为。


默认情况下,响应中唯一的rails行为是隐式地尝试呈现一个名称与动作匹配的模板。 除此之外的任何事情都需要更多的指令,或者使用自定义的respond_to调用来处理多个格式的响应。

由于大多数控制器使用相当常见的自定义模式,响应者通过引入更多的默认行为来提供额外的抽象级别。 读取针对特定格式的调用to_xml / to_json的操作,以及提供相同的mutator操作以及成功的mutator操作的redirect。


有几个机会可以自定义响应者的行为方式,从微妙的调整到完全覆盖或扩展行为。

课程级别: 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或响应调用的类。 另一种方法是将一个或多个模块混入现有的响应者,以超载现有的方法,增加默认行为。

 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操作,这些将是呈现调用,对于其他操作,这将是redirect的选项。 可能最有用的是:location选项,在response_with的参数不足以构build正确的URL的情况下,可用它来覆盖redirectpath。

 # 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不仅提供了一些模块来覆盖一些默认行为。 它使用扩展默认响应者的匿名类来覆盖缺省的响应者,并提供了一个用于在自定义模块中混合这个类的类级方法。 这里最有用的是flash响应器,它提供了一组默认闪烁,将定制委托给I18n系统, config/locales/en.yml

我在以前的项目中使用的自定义响应者的一些例子包括自动装饰我的资源的响应者,并提供了一个默认的页面标题集,其中包含一个用于轻松自定义或覆盖页面标题的界面。