0

In stacking AngularJS ontop of RoR, I'm seen examples of using something like below in model files,

  def as_json(options = {})
    super(options.merge(include: :comments))
  end

My understanding is that this allows the JSON post hash to include the comment hash inside of it. Correct me if I'm wrong.

Fictional example

posts : [
    {id: 0, name: 'friday night', comments: {
        {id: 0, body: "that was a great night"},
        {id: 1, body: "i agree"}
        }   
    }
]

Definition of super from other SO post

super keyword invokes a method with the same name as the current method in the superclass of the current class. ruby super keyword

... so what is super actually doing here?

Community
  • 1
  • 1
tim_xyz
  • 11,573
  • 17
  • 52
  • 97

1 Answers1

1

First, your model extends ActiveRecord::Base, right? For example,

class Post < ActiveRecord::Base 
  # ... 
end 

ActiveRecord::Base defines a as_json method. If you don't define def as_json in your model, you can still call as_json on an instance because it inherits that behavior from its superclass, ActiveRecord::Base.


Second, did you know that ActiveRecord::Base#as_json accepts some options? For example, using only: will restrict the JSON to the attributes you specify (doc).

Given that information, you could call as_json like this:

post.as_json(only: [:title, :published_at]) #=> {title: "...", published_at: "..."}

include: is one of the options which you can pass to as_json.


Third, super is used for calling the same method in a superclass. So, in this case:

class Post < ActiveRecord::Base 
  def as_json(options = {})
    super 
  end 
end 

super will call ActiveRecord::Base#as_json. That's good because that method defines this behavior!

Calling super with no arguments will simply pass the original arguments to that method call. So, these are equivalent:

def as_json(options = {})
  # `options` hash is passed _implicitly_:
  super 
end 

def as_json(options = {})
  # `options` hash is passed _explicitly_:
  super(options)
end

BUT, if you want, you can modify options before sending it to super. In your example, that's what is happening:

def as_json(options = {}) # add include: :comments to any provided options new_options = options.merge(include: :comments) # pass the modified options to super super(new_options) end

This way, you can be sure you're always passing include: :comments to ActiveRecord::Base's implementation of as_json!


Hope that helps!

rmosolgo
  • 1,854
  • 1
  • 18
  • 23