2012-05-19 1 views
2

В моей модели есть родители, дети и названные группы детей. Группы принадлежат родителям, дети принадлежат родителям, а дети могут принадлежать к группе одного и того же родителя.Рельсы: с нетерпением загрузка a принадлежит_to с: условиями, относящимися к себе

Группы могут быть удалены и впоследствии воссозданы с тем же именем, но с другим идентификатором. Ребенок ссылается на свою группу по имени, а не на 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 #<Class:0x00000002dcc290>. self в условиях proc - это класс Child, а не дочерний объект.

Как я могу загрузить такую ​​ассоциацию? Или моя модельная структура просто глупо? Сложные первичные ключи для групп пересекаются разумом, но я бы предпочел, чтобы после того, как rails не поддерживает это по умолчанию.

ответ

0

Похоже, что: параметр 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 
+0

Не работает, извините :(Rails (eager-) загружает группы с отдельной «SELECT .. . FROM groups WHERE name IN (...) AND whatever-is-in-: условия '. Запрос не относится к таблице children. – mpartel

+0

Хммм, хорошо, выглядит так: опция finder_sql будет делать то, что вы хотите. Я также собираюсь обновить свой ответ. – Adam

+0

Не работает. Принадлежность принадлежит в Child не использует finder_sql, и в соответствии с документами вы не можете использовать: finder_sql with belongs_to. – mpartel

0

Я в конечном итоге кодирования вручную примерно то, что 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 

 Смежные вопросы

  • Нет связанных вопросов^_^