我一直在阅读关于respond_with
方法在Rails3中有多酷的文章。但我甚至在Rails API或搜索源代码中都找不到对它的引用。有人能向我解释它是如何工作的吗(你可以使用什么选项等),或者给我指一下它实际实现的地方,这样我就可以自己仔细阅读代码了吗?
针对Rails 4.2的更新+
#respond_with
和::respond_to
(n.b.类方法)不再是Rails的一部分。从Rails 4.2开始,它们被迁移到第三方响应程序gem中(发布说明/提交日期为2014年8月)。虽然默认情况下响应程序不包含在Rails中,但它是Devise的依赖项,因此在许多Rails应用程序中都可用。
然而,#respond_to
实例方法仍然是Rails的一部分(截至本文撰写之时为5.2rc1)。
ActionController::MimeResponds
的官方Rails API文档解释了#respond_to
的工作原理。#respond_with
和::respond_to
的原始Rails Guides文档注释仍然可以在responsers gem源代码中找到。
原始答案
响应程序的代码基于类和模块。MimeResponds,它包含在ActionController::Base中,ApplicationController
继承自该类。然后是ActionController::Responder,它在使用responsd_with时提供默认行为。
默认情况下,rails在响应中提供的唯一行为是隐式尝试呈现具有与操作匹配的名称的模板。除此之外的任何操作都需要操作中的更多指令,或者使用块进行自定义respons_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或响应调用的类。另一种选择是将一个或多个模块混合到现有响应程序中,以重载现有方法,增强默认行为。
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 responsd_with传递的。
实例级别:respond_with
这里的选项是那些将被传递到控制器中的render或redirect_to的选项,但它们仅用于成功场景。对于GET操作,这些将是渲染调用,对于其他操作,这将是重定向选项。其中最有用的可能是:location
选项,它可以用于覆盖重定向路径,以防responsd_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
。
我在以前的项目中使用过的一些自定义响应程序的例子包括一个响应程序,它自动装饰我的资源,并提供了一组默认的页面标题和一个界面,可以轻松地自定义或覆盖页面标题。