按关系过滤活动记录,但不过滤关系本身

时间:2016-02-22 09:39:02

标签: ruby-on-rails activerecord rails-activerecord

我想用一个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 })之类的东西来实现这一目标,但这看起来并不漂亮。

有更好的方法吗?

1 个答案:

答案 0 :(得分:2)

这是includes行动的神奇之处 - 因为您在其中使用bar,它决定使用左连接而不会预先加载任何其他内容。您必须在此明确加入和预先加入关联:

Foo.joins(:bars).where(bars: {foobar: 2}).uniq.preload(:bars)

前段时间我就这些魔法进行了讨论,你可以在这里找到它:https://skillsmatter.com/skillscasts/6731-activerecord-vs-n-1