norim_13
norim_13

Reputation: 303

Query result with tree of referenced objects - Ruby on Rails

I'm currently having a hard time finding a solution for a problem I have in a Ruby on Rails project.

I have the following model structure:

class Room < ActiveRecord::Base
  has_many :photos
end

class Photo < ActiveRecord::Base
  belongs_to :room
  has_many :points
end

class Point < ActiveRecord::Base
  belongs_to :photo
end

I want to query the database so that I get something that rendered as JSON would have this structure:

{
        "rooms" :
            [
                //room 1
                {
                    "id": 1,
                    "param1": "dummy",
                    "photos":
                        [
                            {
                                "id": 3,
                                "title": "test photo",
                                "points":
                                    [
                                        {"id": 1, "text": "test point"},
                                        {"id": 2, "text": "test point"}
                                    ]
                            }
                        ]

                },
                //room 2
                {
                    "id": 2,
                    // ...
                }
            ]
    }
    

Basically, I want to make a query that returns all the info, in all the models, structured according to the models relations.

I searched for a couple of hours and can't find any simple solution for this... (not even complicated one). I don't know if I'm not using the correct search keywords for my problem, but I really couldn't find anything that works...

For a partial solution (to get only rooms and photos), I tried this:

Room.all.includes(:photos)

From what I found, I thought it could be the solution, but it just returns the information about the rooms, not the photos, so probably this is a totally different approach to the one I need.

Upvotes: 1

Views: 188

Answers (3)

Alex Bezek
Alex Bezek

Reputation: 487

@dankohn's answer is correct for eager loading nested associations, but I believe you need a bit more for it to work with to_json. The issue i believe is to_json just looks at the original set of objects and doesn't know about the eager loaded associations. But luckily to_json is a method call that can take the includes as a set hash of options. (Had an issue at in the original code that @norim_13 helped correct. Thanks!!)

Room.all.to_json({:include => { :photos => {:include => { :points => {}} }}})

https://www.tigraine.at/2011/11/17/rails-to_json-nested-includes-and-methods Rails: Eager loading as_json includes

Here is the documentation for as_json http://apidock.com/rails/ActiveModel/Serializers/JSON/as_json

and here in the source for to_json you can see it passes its hash of options to as_json http://apidock.com/rails/Hash/to_json

Upvotes: 3

Jamie G
Jamie G

Reputation: 186

If you get to breaking point, it might be easier just writing a series of .each loops and then just building up the json string manually around them..

Room.all.each do |room|
  room.photos.each do |photo|
    photo.points.each do |point|
      // inner loop
    end
  end
end

Upvotes: 0

Dan Kohn
Dan Kohn

Reputation: 34337

Revised:

What do you get with:

Room.all.includes(photos: :points).to_json

For more info, see Rails - Nested includes on Active Records?

Upvotes: 1

Related Questions