我想用一个has_many关系的模型过滤它的关系值。
使用Foo.include(:bars).where(bars: { foobar: 2 })
可以轻松实现这一目标。
如果我们的数据库中有这样的对象:
{
id: 1,
bars: [
{ id: 4, foobar: 1 },
{ id: 5, foobar: 2 }
]
}
此查询只会返回:
{
id: 1,
bars: [
{ id: 5, foobar: 2 }
]
}
我仍希望通过此关系过滤我的记录,但会收到关系中的所有记录。
我能够通过使用类似Foo.include(:bars).joins('LEFT JOIN bars AS filtered_bars ON filtered_bars.foo_id = foos.id').where(filtered_bars: { foobar: 2 })
之类的东西来实现这一目标,但这看起来并不漂亮。
有更好的方法吗?
答案 0 :(得分:2)
这是includes
行动的神奇之处 - 因为您在其中使用bar
,它决定使用左连接而不会预先加载任何其他内容。您必须在此明确加入和预先加入关联:
Foo.joins(:bars).where(bars: {foobar: 2}).uniq.preload(:bars)
前段时间我就这些魔法进行了讨论,你可以在这里找到它:https://skillsmatter.com/skillscasts/6731-activerecord-vs-n-1