当从Rails 3.1应用程序返回包含“type”属性作为JSON的对象时,似乎不包括“type”属性。假设我有以下内容:
具有相应STI表Animal的模型。 继承动物的猫,狗和鱼的模型。
通过JSON返回Animal时,我希望包含“type”列,但这不会发生:
jQuery.ajax("http://localhost:3001/animals/1", {dataType: "json"});
的产率:
responseText: "{"can_swim":false,"created_at":"2012-01-20T17:55:16Z","id":1,"name":"Fluffy","updated_at":"2012-01-20T17:55:16Z","weight":9.0}"
似乎这是to_json的一个问题:
bash-3.2$ rails runner 'p Animal.first.to_yaml'
"--- !ruby/object:Cat\nattributes:\n id: 1\n type: Cat\n weight: 9.0\n name: Fluffy\n can_swim: false\n created_at: 2012-01-20 17:55:16.090646000 Z\n updated_at: 2012-01-20 17:55:16.090646000 Z\n"
bash-3.2$ rails runner 'p Animal.first.to_json'
"{\"can_swim\":false,\"created_at\":\"2012-01-20T17:55:16Z\",\"id\":1,\"name\":\"Fluffy\",\"updated_at\":\"2012-01-20T17:55:16Z\",\"weight\":9.0}"
有没有人知道这种行为背后的原因,以及如何覆盖它?
答案 0 :(得分:17)
这就是我所做的。它只是将缺少的type
添加到结果集
def as_json(options={})
super(options.merge({:methods => :type}))
end
答案 1 :(得分:6)
覆盖as_json方法。它由to_json
用于产生输出。你可以这样做:
def as_json options={}
{
id: id,
can_swim: can_swim,
type: type
}
end
答案 2 :(得分:0)
对我来说,在Rails 2.3.12中,上述方法不起作用。
我可以(在我的模型中)做这样的事情:
class Registration < ActiveRecord::Base
def as_json(options={})
super(options.merge(:include => [:type]))
end
end
但是这导致to_json抛出这样的错误:
NoMethodError: undefined method `serializable_hash' for "Registration":String
我已经解决了这个问题,这是将这个方法打到我要导出的对象上
class Registration < ActiveRecord::Base
def as_json(options={})
super(options.merge(:include => [:type]))
end
def type
r = self.attributes["type"]
def r.serializable_hash(arg)
self
end
r
end
end
所以在我的应用程序中,我把它放到了mixin中:
module RailsStiModel
# The following two methods add the "type" parameter to the to_json output.
# see also:
# http://stackoverflow.com/questions/8945846/including-type-attribute-in-json-respond-with-rails-3-1/15293715#15293715
def as_json(options={})
super(options.merge(:include => [:type]))
end
def type
r = self.attributes["type"]
def r.serializable_hash(arg)
self
end
r
end
end
现在在我的模型类中,我添加:
include RailsStiModel
答案 3 :(得分:0)
这是我的解决方案,它可以保留as_json的原始功能。
def as_json(options={})
options = options.try(:clone) || {}
options[:methods] = Array(options[:methods]).map { |n| n.to_sym }
options[:methods] |= [:type]
super(options)
end