Reputation: 578
I would like to filter a model with a has_many relation by a value of it's relation.
This is easily achievable by using Foo.include(:bars).where(bars: { foobar: 2 })
.
If we had an object like this in our database:
{
id: 1,
bars: [
{ id: 4, foobar: 1 },
{ id: 5, foobar: 2 }
]
}
This query would only return this:
{
id: 1,
bars: [
{ id: 5, foobar: 2 }
]
}
I would like to still filter my records by this relation, but receive all records in the relation.
I was able to achieve this by using something like: Foo.include(:bars).joins('LEFT JOIN bars AS filtered_bars ON filtered_bars.foo_id = foos.id').where(filtered_bars: { foobar: 2 })
but this does not look very pretty.
Is there a better way to do this?
Upvotes: 2
Views: 99
Reputation: 44675
This is the magic of includes
in action - since you are using bar
in where, it decides to use a left join and will not preload anything else. You have to explicitly join and prelaod the association here:
Foo.joins(:bars).where(bars: {foobar: 2}).uniq.preload(:bars)
Some time ago I made a talk on those magic methods, you can find it here: https://skillsmatter.com/skillscasts/6731-activerecord-vs-n-1
Upvotes: 2