Reputation: 38593
I have trouble understanding why are two duplicate sql queries generated in this situation:
I have a Post which has_many :comments
post = Post.where(id: 4).includes(:comments).first
generates these sql statements:
SELECT "posts".* FROM "posts" WHERE "posts"."id" = 4 LIMIT 1
SELECT "comments".* FROM "comments" WHERE "comments"."post_id" IN (4)
Now:
comment = post.comments.first
(no sql - good)
However:
post = comment.post
generates the same sql:
SELECT "posts".* FROM "posts" WHERE "posts"."id" = 4 LIMIT 1
It seems like the objects are not bound internally. Is there a way I can do that manually to avoid the second sql ?
Upvotes: 5
Views: 521
Reputation: 34072
Use inverse_of
to specify the bi-directional relationship. From the docs:
Specifying the :inverse_of option on associations lets you tell Active Record about inverse relationships and it will optimise object loading.
It may look redundant for simple cases, but associations are 1-way definitions. Specifying inverse_of
lets Rails know that the two relationships are inverse of one another, and solves problems like the one you're having.
# in post.rb
has_many :comments, :inverse_of => :post
# in comment.rb
belongs_to :post, :inverse_of => :comments
Upvotes: 4