Let\'s say I have an app that handles a TODO list. The list has finished and unfinished items. Now I want to add two virtual attributes to the list object; the count of fini
I just thought I'd provide this answer for anyone like myself, who was trying to integrate this into an existing as_json block:
def as_json(options={})
super(:only => [:id, :longitude, :latitude],
:include => {
:users => {:only => [:id]}
}
).merge({:premium => premium?})
Just tack .merge({})
on to the end of your super()
Another way to do this is add this to your model:
def attributes
super.merge({'unfinished' => unfinished_items, 'finished' => finished_items})
end
This would also automatically work for xml serialization. http://api.rubyonrails.org/classes/ActiveModel/Serialization.html Be aware though, you might want use strings for the keys, since the method can not deal with symbols when sorting the keys in rails 3. But it is not sorted in rails 4, so there shouldn't be a problem anymore.
With Rails 4, you can do the following -
render json: @my_object.to_json(:methods => [:finished_items, :unfinished_items])
Hope this helps somebody who is on the later / latest version
just close all of your data into one hash, like
render json: {items: items, finished: finished, unfinished: unfinished}
As Aswin listed above, :methods
will enable you to return a specific model's method/function as a json attribute, in case you have complex assosiations this will do the trick since it will add functions to the existing model/assossiations :D it will work like a charm if you dont want to redefine as_json
Check this code, and please notice how i'm using :methods
as well as :include
[N+Query is not even an option ;)]
render json: @YOUR_MODEL.to_json(:methods => [:method_1, :method_2], :include => [:company, :surveys, :customer => {:include => [:user]}])
Overwritting as_json
function will be way harder in this scenario (specially because you have to add the :include
assossiations manually :/
def as_json(options = { })
end
The serialization of objects in Rails has two steps:
as_json
is called to convert the object to a simplified Hash.to_json
is called on the as_json
return value to get the final JSON string.You generally want to leave to_json
alone so all you need to do is add your own as_json implementation sort of like this:
def as_json(options = { })
# just in case someone says as_json(nil) and bypasses
# our default...
super((options || { }).merge({
:methods => [:finished_items, :unfinished_items]
}))
end
You could also do it like this:
def as_json(options = { })
h = super(options)
h[:finished] = finished_items
h[:unfinished] = unfinished_items
h
end
if you wanted to use different names for the method-backed values.
If you care about XML and JSON, have a look at serializable_hash.