【问题标题】:Rails: eager loading a belongs_to with :conditions refering to selfRails:急切地加载一个belongs_to与:条件引用自我
【发布时间】:2012-05-19 16:07:22
【问题描述】:

在我的模型中,有父母、孩子和指定的孩子组。组属于父母,孩子属于父母,孩子可能属于同一个父母的一组。

组可能会被删除,然后使用相同的名称但不同的 ID 重新创建。一个孩子通过名称而不是 id 来引用它的组,因此如果该组被重新创建,它将属于同一个组。同名的组可能存在多个父母,所以我们需要区分它们。

class Parent < ActiveRecord::Base
  has_many :groups
  has_many :children
end

class Group < ActiveRecord::Base
  belongs_to :parent

  has_many :children,
    :foreign_key => :group_name,
    :primary_key => :name,
    :conditions => proc { "children.parent_id = #{self.parent_id}" }
end

class Child < ActiveRecord::Base
  belongs_to :parent

  belongs_to :group,
    :foreign_key => :group_name,
    :primary_key => :name,
    :conditions => proc { "groups.parent_id = #{self.parent_id}" }
end

在我尝试急切地加载儿童组之前,这非常有效。 Child.where(...).includes(:group)undefined method parent_id' for #&lt;Class:0x00000002dcc290&gt;。条件 proc 中的 self 是 Child 类,而不是 Child 对象。

我如何渴望加载这样的关联?还是我的模型结构很愚蠢?已经想到了组的复合主键,但我宁愿不这样做,因为默认情况下 rails 不支持。

【问题讨论】:

    标签: ruby-on-rails eager-loading belongs-to


    【解决方案1】:

    我最终手动编写了 Rails 在急切加载时所做的代码:

    class Child
      def self.eager_load_groups(children)
        keys = children.map {|c|
          "(#{connection.quote(c.parent_id)}, #{connection.quote(c.group_name)})"
        }
        keys.uniq!
        return if keys.empty?
    
        groups = Group.where('(parent_id, name) IN (' + keys.join(',') + ')')
        groups_by_key = Hash[groups.map {|g| [[g.parent_id, g.name], g] }]
    
        for c in children
          c.group = groups_by_key[[c.parent_id, c.group_name]]
        end
      end
    end
    

    【讨论】:

      【解决方案2】:

      看起来 :finder_sql 选项适用于 has_many 关系。不幸的是,belongs_to 关系不是一个选项。

      class Group < ActiveRecord::Base
        belongs_to :parent
      
        has_many :children,
          :foreign_key => :group_name,
          :primary_key => :name,
          :finder_sql => proc { "select distinct children.id from children where children.parent_id = #{self.parent_id}" }
      end
      

      【讨论】:

      • 不起作用,抱歉 :( Rails (eager-) 使用单独的 'SELECT ... FROM groups WHERE name IN (...) AND what-is-in- 来加载组:条件”。查询不引用子表。
      • 嗯,好的,看起来 :finder_sql 选项可以满足您的需求。我将相应地更新我的答案。
      • 也不起作用。 Child 中的 belongs_to 不使用 finder_sql,根据文档,您不能将 :finder_sql 与 belongs_to 一起使用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多