在rails3中调用to_json时如何包含类名?

时间:2012-03-01 09:30:29

标签: ruby-on-rails-3 json serialization

我正在尝试实现自动完成功能,允许用户从2种不同类型的模型中选择。

这就是我的控制器的外观:

def ac
  arr = []
  arr << Foo.all
  arr << Bar.all
  render json: arr.to_json
end

呈现:

[[{"id":1, "name":"foo name"}], [{"id":1, "name":"bar name"}]]

如何包含类名并获取类似内容:

[
 [{"id":1, "name":"foo name", "class_name":"Foo"}],
 [{"id":1, "name":"bar name", "class_name":"Bar"}]
]

2 个答案:

答案 0 :(得分:1)

如果你不介意做一些额外的工作,你可以使用:methods方法as_json方法(以及to_json)来做那样的事情:

class Foo
  def class_name
    self.class.name
  end
end

arr = Foo.all.map { |foo| foo.as_json(:methods => [:class_name]) }
puts arr.to_json
#=> [{ "id": 1, "name": "foo name", "class_name": "Foo" }]

如果您将ActiveRecord::Base.include_root_in_json设置为true(默认为afaik),那么您将获得类似

的哈希值
{ "foo": { "id": 1, "name": "foo name" } }

如果您希望它完全是类名,您可以传递:root选项:

foo = Foo.last
puts foo.to_json(:root => foo.class.name)
#=> { "Foo": { "id": 1, "name": "foo name" } }

请注意,这两种解决方案都不允许您只是在记录数组上调用to_json。要克服此问题并默认包含class_name,您可以在模型中覆盖serializable_hash方法:

def serializable_hash(*)
  super.merge('class_name' => self.class.name)
end

如果将其包装到模块中,则可以将其包含在所需的任何模型中,并将class_name包含在as_jsonto_json的结果中,而不会向这些方法传递任何额外选项。如果要在某些情况下排除:except,可以稍微修改实施以尊重class_name选项。

答案 1 :(得分:0)

最后增加了1个步骤:

arr << Foo.all
arr << Bar.all
arr.flatten!
arr=arr.collect{|itm| {"id":"#{itm.class.to_s}:#{itm.id}", "value":itm.name}}

然后我吐了出来:

render json: arr.to_json()

结果我得到了:

[{"id":"Foo:1", "value":"Foo #1"},{"id":"Bar:1", "value":"Bar #1"}]