【问题标题】:Select objects based on grandchild attribute with joins in ActiveRecord在 ActiveRecord 中根据带有连接的孙属性选择对象
【发布时间】:2014-03-28 18:23:50
【问题描述】:

假设我有以下模型:

class Foo < ActiveRecord::Base
has_many :bars
has_many :bazs, :through => :bars

class Bar < ActiveRecord::Base
belongs_to :foo
has_many :bazs

class Baz < ActiveRecord::Base
belongs_to :bar

假设 Baz 有一个“名称”属性。选择 Baz 名称为“x”的所有 Foo 的最佳方法是什么?

我原以为我可以做类似Foo.join(:baz).where('bazs.name' =&gt; 'x') 的事情,但这似乎行不通。

【问题讨论】:

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


    【解决方案1】:

    这应该可以了!

    Foo.joins(:bazs).where(bazs: {name: 'x'})
    

    【讨论】:

    • 可以发誓我尝试了几次,但都没有成功。再次尝试成功。谢谢!也为了其他人发现这个......通过添加 .group('foos.id') 避免重复
    • @Patm 避免使用 includes 而不是 joins 重复
    • @MrYoshiji 是的,你是对的。我检查了这两种方法,并且使用组连接实际上比包含要快得多……至少对于我的大型样本数据集而言。
    【解决方案2】:

    您可以包含它们声明的关系:

    Foo.includes(bars: :bazs)
    

    然后您可以在包含的表格上应用您的条件:

    Foo.includes(bars: :bazs).where(bars: { title: 'Hey'}, bazs: { id: nil })
    

    由于您已经通过“has_many-through”关系在 Foo 模型中声明了 :bazs,您可以这样做:

    Foo.includes(:bazs).where(bazs: { id: 12 })
    

    【讨论】:

    • 谢谢 - 但如果涉及曾孙辈并且您想浏览另一张桌子,第一反应会如何变化?
    • @BKSpureon 如果您正在谈论具有任何深度的自引用关系(例如 Category has_many :child_categories 并且每个 child_categories 也可以有孩子,等等),那么我强烈建议使用SQL VIEW 使用递归来模拟祖先/后代关系。它将为您节省很多性能。
    • 不,这对 Rails 来说太复杂了,而且涉及到一些 SQL 知识。您可以在 Google 上轻松找到父/子关系的递归视图示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多