【发布时间】:2011-04-21 19:15:48
【问题描述】:
我正在 Rails 3 中实现一个 REST API。我们允许 JSON 和 XML 作为响应格式。
默认respond_with 可以正常工作,只要您只想返回请求的资源,例如:
def show
respond_with User.find(params[:id])
end
GET /users/30.xml
<?xml version="1.0" encoding="UTF-8"?>
<user>
<birthday type="date">2010-01-01</birthday>
<company-name>Company</company-name>
<email>email@test.com</email>
<id type="integer">30</id>
</user>
但是,我希望得到以下标准化回复:
<?xml version="1.0" encoding="UTF-8"?>
<response>
<status>
<success type="boolean">true</success>
</status>
<result>
<user>
<birthday type="date">2010-01-01</birthday>
<company-name>Company</company-name>
<email>email@test.com</email>
<id type="integer">30</id>
</user>
</result>
</response>
我怎样才能达到这个结果?
我尝试了以下方法,使用自定义响应类
class Response
STATUS_CODES = {
:success => 0,
}
extend ActiveModel::Naming
include ActiveModel::Serializers::Xml
include ActiveModel::Serializers::JSON
attr_accessor :status
attr_accessor :result
def initialize(result = nil, status_code = :success)
@status = {
:success => (status_code == :success),
}
@result = result
end
def attributes
@attributes ||= { 'status' => nil, 'result' => nil }
end
end
并在我的ApplicationController 中重新定义respond_with 方法:
def respond_with_with_api_responder(*resources, &block)
respond_with_without_api_responder(Response.new(resources), &block)
end
alias_method_chain :respond_with, :api_responder
但是,这并没有产生预期的结果:
<?xml version="1.0" encoding="UTF-8"?>
<response>
<status>
<success type="boolean">true</success>
</status>
<result type="array">
<result>
<birthday type="date">2010-01-01</birthday>
<company-name>Company</company-name>
<email>email@test.com</email>
<id type="integer">30</id>
</result>
</result>
</response>
应该是<user> 现在又是<result>。当我返回一个数组作为结果时,情况会变得更糟,然后我会得到另一个<result> 层。如果我查看 JSON 响应,它看起来几乎没有问题——但请注意,有一个数组 [] 过多地包装了用户资源。
GET /users/30.json
{"response":{"result":[{"user":{"birthday":"2010-01-01","company_name":"Company","email":"email@test.com"}}],"status":{"success":true}}}
有什么线索吗?如何获得所需的响应格式?我也尝试过编写一个自定义的Responder 类,但归结为在ActionController:Responder 中重写display 方法,这给了我完全相同的问题:
def display(resource, given_options={})
controller.render given_options.merge!(options).merge!(format => Response.new(resource))
end
我相信问题在某种程度上隐藏在ActiveModel 的序列化代码中,但我似乎无法弄清楚如何将资源包装在容器标签中,并且仍然实现包装的资源被正确序列化。
有什么想法或想法吗?
【问题讨论】:
标签: ruby-on-rails ruby-on-rails-3 api rest