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.
The best answer for me was using serializable_hash
. @kikito touched on this in his comment, but there was a typo that prevented it from working. It's not serialized_hash
, it's serializable_hash
.
Literally just find + replace as_json
with serializable_hash
and this bug goes away. (It's still not fixed in today's Rails 4.0.2). You also get the benefit of having an easier time implementing an XML API later (some people still use those!).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With