I’m running into an issue where I’m working with the as_json method, and how to efficiently return the object in JSON AND it’s belongs_to object as JSON as well, where the belongs_to object has its own belongs_to object. Code would probably explain it better.
The Not-Working Way
Alert class
class Alert < ActiveRecord::Base
belongs_to :message
# for json rendering
def as_json(options={})
super(:include => :message)
end
end
Message class
def as_json(options={})
super( methods: [:timestamp, :num_photos, :first_photo_url, :tag_names],
include: { camera: { only: [:id, :name] },
position: { only: [:id, :name, :address, :default_threat_level ]},
images: { only: [:id, :photo_url, :is_hidden]} })
end
The problem with this first set up is that when I have an Alert object and call
alert.as_json()
I get all the attributes from Alert and all the attributes from Message, but none of the other attributes from Message that I want, like Camera, Position, etc.
Here’s the “It’s Working, But Probably Not Proper Design Way”
Alert Class
class Alert < ActiveRecord::Base
belongs_to :message
# for json rendering
def as_json(options={})
super().merge(:message => message.as_json)
end
end
Messages Class
# for json rendering
def as_json(options={})
super( methods: [:timestamp, :num_photos, :first_photo_url, :tag_names])
.merge(:camera => camera.as_json)
.merge(:position => position.as_json)
.merge(:images => images.as_json)
end
In this 2nd setup, I get all of Messages’s nested attributes like I want.
My question, am I missing some Rails Convention to do this properly? It seems like there would/should be an easier way.
Which version of Rails are you using? This is a known bug in older versions of Rails, supposedly fixed with this pull request. Your syntax looks right to me, so perhaps this is your problem?
As an aside, you may also want to checkout the new active_model_serializers from Jose Valim (Rails core member). It may at least enable you to work around your issue in a more elegant manner.