Rails response_with:它是如何工作的?


128

我一直在这里阅读有关该respond_with方法在Rails 3中有多酷的信息,但是我什至在Rails API或搜索源中都找不到该方法的引用。谁能向我解释它的工作原理(可以使用哪些选项等)或将其指向实际实现的位置,以便我自己阅读代码?

Answers:


128

Rails 4.2以上的更新

#respond_with::respond_tonb类方法)不再是Rails的一部分。从Rails 4.2(发行说明 / 2014年8月提交)开始,它们已迁移到第三方响应程序中。虽然默认情况下响应器未包含在Rails中,但是它是Devise的依赖项,因此在许多Rails应用程序中都可用。

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

官方的Rails API文档ActionController::MimeResponds解释了如何#respond_to工作。原始的《 Rails指南》文档注释为#respond_with::respond_to并且仍然可以在响应者gem源代码中找到


原始答案

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


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

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


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

课程等级: 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

尽管可能存在一些有趣的边缘用例,但将模块扩展或混合到默认响应器中的可能性更大。在任何情况下,相关的选项都是资源和选项,因为它们是从respond_with中传递的。

实例级别: respond_with

此处的选项是将传递给控制器​​中的render或redirect_to的选项,但仅在成功方案中包含这些选项。对于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响应器,它提供一组默认的闪光灯,默认情况下将自定义委托给I18n系统config/locales/en.yml

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


1
我想你的意思是(在类体内)self.responder =刚刚responder =将分配给地方
horseyguy

谢谢!location选项的存在是我需要的信息!
JellicleCat 2014年

1
该解释是否仍然与Rails 4/5相关?我听说respond_with过时了,但是我不知道为什么。
阿伦2015年

1
@ Arnlen,response_with被提取为单独的宝石“ 响应者
Nick Roz

请注意,要使闪光灯config/locales/en.yml正常工作,您需要responders :flash控制器顶部。
bjnord
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.