I'm trying to implement autocomplete that lets user to pick from list of 2 different kind of models.
This is how my controller looks:
def ac
arr = []
arr << Foo.all
arr << Bar.all
render json: arr.to_json
end
Which renders:
[[{"id":1, "name":"foo name"}], [{"id":1, "name":"bar name"}]]
How to include class name and get something like this:
[
[{"id":1, "name":"foo name", "class_name":"Foo"}],
[{"id":1, "name":"bar name", "class_name":"Bar"}]
]
?
If you don't mind doing a bit of extra work you can do smth like that with :methods
option of as_json
method (and to_json
as well):
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" }]
If you have ActiveRecord::Base.include_root_in_json
set to true
(that is default afaik) then you'll get hashes like
{ "foo": { "id": 1, "name": "foo name" } }
If you want it to be exactly the class name you can pass :root
option:
foo = Foo.last
puts foo.to_json(:root => foo.class.name)
#=> { "Foo": { "id": 1, "name": "foo name" } }
Note that both these solutions do not allow you simply to call to_json
on an array of records. To overcome that and make class_name
included by default you can override serializable_hash
method in your model like that:
def serializable_hash(*)
super.merge('class_name' => self.class.name)
end
If you wrap it into a module you can include it in any model you want and get class_name
included into the result of as_json
or to_json
without passing any extra options to these methods. You can modify the implementation a bit to respect :except
option if you want to exclude class_name
in some cases.