Rails respond_with:它是如何工作的?

jay*_*del 122 ruby-on-rails ruby-on-rails-3

我一直在这里阅读respond_withRails 3中的方法有多酷.但我甚至无法在Rails API或搜索源中找到它的引用.任何人都可以向我解释它是如何工作的(你可以使用哪些选项等)或指向我实际实现的地方所以我可以自己仔细阅读代码?

Clu*_*ter 124

Rails 4.2+的更新

#respond_with::respond_to(nb类方法)不再是Rails的一部分.从Rails 4.2 开始,他们被迁移到第三方响应者宝石(发布说明/提交日期为2014年8月).虽然默认情况下响应程序不包含在Rails中,但它是Devise的依赖项,因此可用于许多Rails应用程序.

#respond_to 实例方法,然而,仍然轨道的一部分(5.2rc1撰写本文时).

官方Rails API文档ActionController::MimeResponds解释了如何#respond_to工作.对于原来的Rails指南文档注释#respond_with,并::respond_to仍然可以在发现应答宝石的源代码.


原始答案

响应者的代码基于类和模块.MimeResponds包含在ActionController :: Base中,这是您ApplicationController继承的类.然后是ActionController :: Responder,它在使用respond_with时提供默认行为.


默认情况下,响应中提供的唯一行为是隐式尝试呈现名称与操作匹配的模板.除此之外的任何内容都需要操作中的更多指令,或者使用块来自定义respond_to调用以处理多种格式响应.

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


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

班级: respond_to

在此处指定Responder应处理的格式.可以定制格式以确定它们将应用于哪些操作.可以使用单独的调用指定每种格式,从而允许完全自定义每种格式的操作.

# 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]
Run Code Online (Sandbox Code Playgroud)

班级: 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
Run Code Online (Sandbox Code Playgroud)

虽然可能存在一些有趣的边缘用例,但更有可能将模块扩展或混合到默认响应器中将是更常见的模式.在任何情况下,相关的选项都是资源和选项,因为它们是从来自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'))
Run Code Online (Sandbox Code Playgroud)

作为替代方案,响应者 gem不仅提供一些模块来覆盖某些默认行为.它使用扩展默认响应程序的匿名类覆盖默认响应程序,并提供类级别方法,以便将自定义模块混合到此类中.这里最有用的是闪回响应器,它提供了一组默认闪存,默认情况下将自定义委派给I18n系统config/locales/en.yml.

我在以前的项目中使用自定义的反应的一些例子包括应答自动装饰了我的资源,并提供了页面标题的一套默认的界面轻松定制或重写网页标题.