Reputation: 783
class Parent < ApplicationRecord
has_one: child
end
class Child < ApplicationRecord
belongs_to :parent
end
childrens = Child.includes(:parent)
puts childrens.to_json
[{"id":1,"parent_id":1,"name":"Jack"},{"id":2,"parent_id":2,"name":"Oleg"}]
In this case, we can access parent object like this: child.parent
But it is not possible to access parent object in view. Is there any way to include parent objects in each child?
Thank you!
Upvotes: 1
Views: 174
Reputation: 783
Child.includes(:parent).as_json(include: :parent)
This helped me!
Upvotes: 0
Reputation: 33420
You can use as_json
with the include
option to get each child parent:
Child.includes(:parent).as_json(include: :parent)
For that you get a couple of queries. One for the children, the other one for each children parents (IN clause):
Child Load (1.0ms) SELECT "children".* FROM "children"
Parent Load (1.2ms) SELECT "parents".* FROM "parents" WHERE "parents"."id" IN ($1, $2) [["id", 1], ["id", 2]]
You can limit the columns you're retrieving from the database (with select
) as well as each object in the JSON object (that doesn't apply a SQL filter).
Upvotes: 3
Reputation: 2834
There is a bit of confusion which you made with includes
. This will not include the objects, but prepares them in case they are needed.
Because you have an association between Parent
and Child
, you can already get the parents in view, but this will request the parent for every children hence you'll run in n+1 queries.
To put it in code:
Child.all.each { |c| c.parent }; nil
will trigger:
Parent Load (0.2ms) SELECT "parents".* FROM "parents" WHERE "parents"."id" = $1 LIMIT 1 [["id", 4750516]]
Parent Load (0.2ms) SELECT "parents".* FROM "parents" WHERE "parents"."id" = $1 LIMIT 1 [["id", 4772539]]
Parent Load (0.1ms) SELECT "parents".* FROM "parents" WHERE "parents"."id" = $1 LIMIT 1 [["id", 4806512]]
What you do there with includes, will make it look like:
SELECT "children".* FROM "children"
Parent Load (3.3ms) SELECT "parents".* FROM "parents" WHERE "parents"."id" IN (4750516, 4772539, 4806512)
So, if you want to use it in the view, you'll actually have something like @childrens
so don't be afraid to iterate over and call .parent
.
You can read more about eager loading here
Upvotes: 0