2

我需要使用 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 不会,反之亦然。一旦我的基本功能正常工作,我想添加额外的方法来获取整个谱系、祖父母、兄弟姐妹、后代等。

问题:

  1. 我如何将性别条件应用于父母而不是马,以便父亲和母亲都起作用。

  2. 我采取的方法是可行的,还是有更优雅、更有效的方法来实现这一点。

  3. 任何其他建议或指导将不胜感激。

很抱歉这个问题很长,感谢您的帮助。

4

2 回答 2

2

我可能会开始:

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
于 2013-01-31T01:34:16.650 回答
0

我最终花了很多时间在这个上,但最终想出了一个满足我要求的解决方案。最终起作用的协会如下:

  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

问题回复:

我通过使用一个关联代理和一个简单的包装器来应用性别条件。我创建了一个 dam_relationship 和相应的 Sire_relationship,然后将这些方法包装在几个 dam 和 Sire 包装器方法中。

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)

以及下面提到的祖先宝石中包含的大多数方法。稍微递归一下,就可以相当直接地显示整个谱系或您感兴趣的世代数。

与直接在 Horse 模型中使用sire_id 和 dam_id 相比,我决定使用两个模型(Horse 和 Pedigree)的方法提供了一些额外的灵活性。这种方法将使我能够更轻松地创建像@horse.uncle、@horse.aunt 这样的方法。我相信直接在 Horse 模型中使用sire_id 和 dam_id 会更困难。

实现这一点的最受欢迎的宝石似乎是祖先。作者通过在感兴趣的模型中添加祖先列来实现这一点,而且更简单。这是一个非常好的解决方案,绝对值得一试。

于 2013-02-09T15:17:49.823 回答