我需要使用rails/activerecord对多达5或6代的马血统进行建模。 我在堆栈和网络上进行了研究,并最终将本文用作我方法的基础。这是我想到的。
两种型号:
Horse has the following attributes id and horse_name
Pedigree has: id, parent_id and horse_id.
以及以下关联:
has_many :parent_horse_relationships, :class_name => "Pedigree", :foreign_key => :horse_id, :dependent => :destroy
has_one :sire_horse_relationship, :class_name => "Pedigree", :foreign_key => :horse_id, :conditions => "horse_gender = 'Male'
has_one :dam_horse_relationship, :class_name => "Pedigree", :foreign_key => :horse_id, :conditions => "horse_gender = 'Female'
has_many :parents, :through => :parent_horse_relationships, :source => :parent
has_one :sire, :through => :sire_horse_relationship,:source => :parent
has_one :dam, :through => :dam_horse_relationship,:source => :parent
has_many :horse_parent_relationships, :class_name => "Pedigree", :foreign_key => :parent_id, :dependent => :destroy
has_many :progenies, :through => :horse_parent_relationships, :source => :horse
这种方法很接近,但是我确定母亲或父亲的条件似乎是应用于马而不是父母。 因此,如果特定的马是雄性,horse.sire将起作用,但horse.dam不会,反之亦然。 一旦我获得基本功能,我想添加其他方法来获取整个血统、祖父母、兄弟姐妹、后代等。
问题:
我怎样才能将性别条件应用于父母而不是马匹,以便父亲和母亲都起作用。
我采取的方法是否可行,或者是否有更优雅、更有效的方法来实现这一点。
任何其他建议或指导将不胜感激。
对于这个冗长的问题,我们深表歉意,并感谢您的帮助。
我可能会从:
has_one :sire, :class_name => "Pedigree", :foreign_key => :horse_id, :conditions => "horse_gender = 'Male'
has_one :dam, :class_name => "Pedigree", :foreign_key => :horse_id, :conditions => "horse_gender = 'Female'
has_many :parent_horse_relationships, :class_name => "Pedigree", :foreign_key => :horse_id, :dependent => :destroy
has_many :parents, :through => :parent_horse_relationships, :source => :parent
has_many :progenies, :through => :horse_parent_relationships, :source => :horse
我最终在这个问题上花费了大量时间,但最终提出了一个满足我要求的解决方案。 最终起作用的协会如下:
has_many :parent_horse_relationships, :class_name => "Pedigree", :foreign_key => :horse_id, :dependent => :destroy
has_many :parents, :through => :parent_horse_relationships, :source => :parent do
def dam_relationship
owner = self.proxy_association.owner
owner = owner.parents.where(:horse_gender => "Female")
where('pedigrees.parent_id = ?', owner)
end
def sire_relationship
owner = self.proxy_association.owner
owner = owner.parents.where(:horse_gender => "Male")
where('pedigrees.parent_id = ?', owner)
end
end
def dam
parents.dam_relationship
end
def sire
parents.sire_relationship
end
问题回答:
我通过使用association_proxy和简单的包装来应用性别条件。我创建了一个dam_relationship和相应的sire_relationship,然后将这些方法包装在几个dam和sear包装器方法中。
def dam_relationship
owner = self.proxy_association.owner
owner = owner.parents.where(:horse_gender => "Female")
where('pedigrees.parent_id = ?', owner)
end
def dam
parents.dam_relationship
end
这允许我执行以下操作:
@horse.parents, @horse.dam, @horse.sire (not displayed)
以及下面提到的祖先宝石中包含的大多数方法。只需一点递归,就可以相当直接地显示整个谱系或您感兴趣的世代数。
我决定,与直接在马模型中使用sire_id和dam_id相比,拥有两个模型(马和血统)的方法提供了额外的灵活性。这种方法将使我能够更轻松地创建方法,例如@horse.uncle,@horse.aunt。 我相信这些会更困难,直接在 Horse 模型中使用sire_id和dam_id。
实现这一目标最受欢迎的宝石似乎是血统。 作者通过向感兴趣的模型添加祖先列来实现这一目标,并且更简单。这是一个非常好的解决方案,绝对值得一试。