Rails response_with: 它是如何工作的?

我一直在到处阅读关于 Rails 3中 respond_with方法有多酷的文章。但是我甚至不能在 Rails API 或者通过搜索源代码找到对它的引用。有没有人可以向我解释一下它是如何工作的(你可以使用哪些选项,等等) ,或者告诉我它实际实现的地方,这样我就可以自己仔细阅读代码了?

99527 次浏览

Rails 4.2 + 更新

#respond_with::respond_to(N.b.类方法)是 不再是 Rails 的一部分。从 Rails 4.2(释放通知书/承诺日期为2014年8月)开始,它们被迁移到第三方 应急人员 gem 中。虽然默认情况下 Rails 中不包含响应器,但它是 Devise 的一个依赖项,因此在许多 Rails 应用程序中都可以使用。

然而,#respond_to 实例方法,仍然是 Rails 的一部分(撰写本文时为5.2 rc1)。

ActionController::MimeResponds的官方 Rails API 文档解释了 #respond_to是如何工作的。#respond_with::respond_to的原始 Rails Guides 文档注释仍然可以在 响应者宝石源代码中找到。


原始答案

响应者的代码基于一个类和一个模块。包含在 基地中的 MimeResponseApplicationController从该类继承。然后是 响应者,它在使用 response _ with 时提供默认行为。


默认情况下,Rails 在响应中提供的唯一行为是隐式尝试呈现名称与操作匹配的模板。除此之外,还需要操作中的更多指令,或者使用一个块来处理多种格式响应的自定义 response _ 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]

班级等级: responder

这是保存响应者的 class 属性。这可以是响应调用的任何东西,这意味着您可以使用 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

虽然可能会有一些有趣的边缘用例,但更可能的情况是,将模块扩展或混合到默认响应器中将是更常见的模式。在任何情况下,相关的选项是资源和选项,因为它们是从 response _ with 传递过来的。

实例级别: respond_with

这里的选项是那些将被传递到控制器中呈现或重定向到的选项,但它们只包含在成功场景中。对于 GET 操作,这些是呈现调用,对于其他操作,这些是重定向选项。其中最有用的可能是 :location选项,如果 response _ 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 不仅提供了一些模块来重写一些默认行为。它使用一个扩展默认响应器的匿名类重写默认响应器,并提供一个类级别方法,用于将自定义模块混合到此类中。这里最有用的是 flash 响应器,它提供一组默认的 flash,将定制委托给 I18n 系统,默认情况下是 config/locales/en.yml

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