Add virtual attribute for json output

Say I have an application that processes a TODO list. The list is complete and unfinished items. Now I want to add two virtual attributes to the list object; the number of finished and unfinished items in the list. I also need them to appear on json output.

I have two methods in my model that retrieve unfinished / finished items:

def unfinished_items self.items.where("status = ?", false) end def finished_items self.items.where("status = ?", true) end 

So, how can I get the number of these two methods in my json file?

I am using Rails 3.1

+48
json ruby-on-rails
Jul 31 '11 at 20:16
source share
7 answers

Serializing objects in Rails consists of two steps:

  • First, as_json is called to convert the object to a simplified hash.
  • Then to_json is called in the returned as_json value to get the final JSON string.

Usually you want to leave to_json yourself, so all you have to do is add your own as_json implementation like the following:

 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 can also do it like this:

 def as_json(options = { }) h = super(options) h[:finished] = finished_items h[:unfinished] = unfinished_items h end 

if you want to use different names for the values ​​supported by the method.

If you're interested in XML and JSON, check out serializable_hash .

+94
Jul 31 2018-11-11T00:
source share

With Rails 4 you can do the following -

 render json: @my_object.to_json(:methods => [:finished_items, :unfinished_items]) 

Hope this helps someone who is on the latest / latest version

+20
Nov 19 '14 at
source share

Another way to do this is to add this to your model:

 def attributes super.merge({'unfinished' => unfinished_items, 'finished' => finished_items}) end 

This will also automatically work for xml serialization. http://api.rubyonrails.org/classes/ActiveModel/Serialization.html However, keep in mind that you may need strings for keys, since the method cannot process characters when sorting keys in rails 3. But it does not sort in rails 4 therefore there should be no more problems.

+13
Jul 09 '13 at 16:57
source share

just close all your data in one hash , for example

render json: {items: items, finished: finished, unfinished: unfinished}

+1
May 18 '15 at 15:41
source share

I just thought that I would give this answer to everyone, like me, 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 hit .merge({}) at the end of your super()

0
Mar 22 '15 at 19:42
source share

This will be done without performing some ugly overloads. If you got a List model, for example, you can put it in your controller:

  render json: list.attributes.merge({ finished_items: list.finished_items, unfinished_items: list.unfinished_items }) 
0
Nov 29 '17 at 2:53 on
source share

As Aswin above :methods will allow you to return a specific model method / function as a json attribute if you have a complex association will do the trick since it will add functions to the existing model / associations: D will work like a charm if you don’t want to override as_json

Check out this code and notice how I use :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]}])

The Overwritting as_json function will be more complicated in this scenario (especially because you must add the interlocutors :include manually: / def as_json(options = { }) end

0
Nov 29 '17 at 19:34 on
source share



All Articles