繁体   English   中英

Rails respond_with:它是如何工作的?

[英]Rails respond_with: how does it work?

我一直在这里和那里阅读关于 Rails 3 中的respond_with方法有多酷。但我什至在 Rails API 或搜索源代码中都找不到对它的引用。 任何人都可以向我解释它是如何工作的(您可以使用哪些选项等),或者将我指向它实际实现的位置,以便我可以自己仔细阅读代码?

Rails 4.2+ 更新

#respond_with::respond_tonb class 方法)不再是 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 文档注释仍然可以在响应者 gem 源代码中找到。


原始答案

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


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

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


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

Class 级别: 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 级别: responder

这是一个包含响应者的 class 属性。 这可以是响应调用的任何内容,这意味着您可以使用响应调用的 proc/lambda 或 class。 另一种选择是将一个或多个模块混合到现有响应程序中以重载现有方法,从而增强默认行为。

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_with 传递过来的。

实例级别: respond_with

这里的选项是那些将被传递给 controller 中的 render 或 redirect_to 的选项,但它们仅包含在成功场景中。 对于 GET 操作,这些将是渲染调用,对于其他操作,这将是重定向的选项。 其中最有用的可能是:location选项,它可用于覆盖该重定向路径,以防 respond_with 的 arguments 不足以构建正确的 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 不仅提供了一些模块来覆盖一些默认行为。 它使用扩展默认响应器的匿名 class 覆盖默认响应器,并提供 class 级别的方法来混合自定义模块到此 class。 这里最有用的是 flash 响应程序,它提供了一组默认的 flash,将自定义委托给 I18n 系统,默认为config/locales/en.yml

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM