我到处都在读Rails 3中的respond_with方法有多酷.我甚至无法在Rails或源代码中找到它.有没有人可以向我解释一下它是如何工作的(你可以使用什么选项等等),或者告诉我它实际实现的地方,这样我就可以自己阅读代码了?

推荐答案

Rails 4.2的更新+

#respond_with::respond_to(n.b.类方法)是no longer a part of Rails.从Rails 4.2(2014年8月发布的release notes/commit)起,它们被移植到第三方responders gem中.虽然默认情况下Rails中不包含响应程序,但它依赖于Desive,因此在许多Rails应用程序中都可用.

然而,#respond_toinstance method,still a part of Rails(截至本文 compose 时为5.2rc1).

ActionController::MimeResponds的官方Rails API文档解释了#respond_to的工作原理.#respond_with::respond_to的原始Rails指南文档注释仍然可以在responders gem source code中找到.


原始答案

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


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

由于大多数控制器使用一种相当常见的定制模式,响应者通过引入更多默认行为来提供额外的抽象级别.阅读调用_xml/to_json以获取特定格式的操作,以及提供相同格式的mutator操作,以及成功执行mutator操作的重定向.


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

Class Level: 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]

Class Level: responder

这是一个保存响应者的类属性.这可以是响应调用的任何东西,这意味着您可以使用proc/lambda或响应调用的类.另一种 Select 是将一个或多个模块混合到现有响应程序中,以重载现有方法,从而增强默认行为.

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_传递的.

Instance Level: respond_with

这里的选项是那些将被传递到控制器中渲染或重定向到的选项,但它们仅用于成功场景.对于GET操作,这些将是呈现调用,对于其他操作,这些将是重定向选项.在这种情况下,这些参数中的哪一个可能不足以覆盖正确的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不仅提供了一些用于覆盖某些默认行为的模块.它用一个扩展默认响应程序的匿名类覆盖默认响应程序,并提供一个类级方法,用于将自定义模块混合到该类中.这里最有用的是flash responder,它提供了一组默认的flash,默认情况下将定制委托给I18n系统config/locales/en.yml.

我在以前的项目中使用过的一些自定义响应程序示例包括一个自动修饰我的资源的响应程序,并提供了一组默认的页面标题,带有一个界面,可以轻松自定义或覆盖页面标题.

Ruby-on-rails相关问答推荐

Rails 7 中的预编译

如何使用 activerecord activerecord-session_store 在 Rails 应用程序中使用 cookie 值在数据库中查找会话记录

您如何查看在 Rails 中触发回调的关联模型?

显示每个 rspec 示例的运行时

Restful Rails 编辑与更新

Rails - 按连接表数据排序

验证以确保唯一性但忽略空值?

Rails 和 OS X:如何安装 rmagick?

没有图像时如何在回形针中显示隐藏图像

rails回形针和乘客`'识别'命令无法识别`

如何在 Rails 中测试助手?

如何使用 Ruby 在现有 PDF 上编辑或书写?

获取磁盘上 ActiveStorage 文件的路径

如何在 RSpec 中包含 Rails 助手

Rails HABTM - 正确删除关联

设计:在注册期间禁用密码确认

快速添加链接[:notice]

如何为 rspec 设置 ENV 变量?

Rails 路由:GET 没有参数 :id

ActiveRecord 何时会保存关联?