我应该如何在铁轨中模拟马谱系?

时间:2013-01-31 01:21:30

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

我需要使用rails / activerecord模拟最多5或6代马谱系。我在堆栈和网络上进行了我的研究,并最终利用这个article作为我的方法的基础。这就是我想出来的。

两种型号:

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将起作用,但是马.dam将不会,反之亦然。一旦我获得基本功能,我想添加其他方法来获得整个血统,祖父母,兄弟姐妹,后代等。

问题:

  1. 我如何将性别条件应用于父母而不是马,以便父母和大坝都能正常工作。

  2. 我采取的方法是否可行,或者是否有一种更优雅,更有效的方法来实现这一目标。

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

  4. 为长期问题道歉并感谢您的帮助。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

问题回复:

我通过使用association_proxy和一个简单的包装来应用性别条件。我创建了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这样的方法。我相信在马模型中直接使用sire_id和dam_id会更加困难。

实现这一目标的最受欢迎的宝石似乎是ancestry。作者通过在感兴趣的模型中添加祖先列来完成此操作并简单地完成此操作。这是一个非常好的解决方案,绝对值得一试。