繁体   English   中英

Rails模型has_many有多个foreign_keys

[英]Rails Model has_many with multiple foreign_keys

相对较新的rails并尝试使用具有name,gender,father_id和mother_id(2个父项)的单个Person模型来建模一个非常简单的族“树”。 下面基本上是我想要做的,但显然我不能重复:has_many中的孩子(第一个被覆盖)。

class Person < ActiveRecord::Base
  belongs_to :father, :class_name => 'Person'
  belongs_to :mother, :class_name => 'Person'
  has_many :children, :class_name => 'Person', :foreign_key => 'mother_id'
  has_many :children, :class_name => 'Person', :foreign_key => 'father_id'
end

是否有一种简单的方法可以将has_many与2个外键一起使用,或者根据对象的性别更改外键? 或者还有其他/更好的方式吗?

谢谢!

在IRC上找到一个似乎有效的简单答案(感谢雷达):

class Person < ActiveRecord::Base
  belongs_to :father, :class_name => 'Person'
  belongs_to :mother, :class_name => 'Person'
  has_many :children_of_father, :class_name => 'Person', :foreign_key => 'father_id'
  has_many :children_of_mother, :class_name => 'Person', :foreign_key => 'mother_id'
  def children
     children_of_mother + children_of_father
  end
end

为了改进Kenzie的答案,你可以通过定义Person#children来实现ActiveRecord关系:

def children
   children_of_mother.merge(children_of_father)
end

有关详细信息,请参阅此答案

在Person模型上使用named_scopes执行以下操作:

class Person < ActiveRecord::Base

    def children
      Person.with_parent(id)
    end

    named_scope :with_parent, lambda{ |pid| 

       { :conditions=>["father_id = ? or mother_id=?", pid, pid]}
    }
 end

我相信你可以使用:has_one实现你想要的关系。

class Person < ActiveRecord::Base
  has_one :father, :class_name => 'Person', :foreign_key => 'father_id'
  has_one :mother, :class_name => 'Person', :foreign_key => 'mother_id'
  has_many :children, :class_name => 'Person'
end

我会在下班后确认并编辑这个答案;

我更喜欢使用范围来解决这个问题。 像这样:

class Person < ActiveRecord::Base
  belongs_to :father, :class_name => 'Person'
  belongs_to :mother, :class_name => 'Person'
  has_many :children_of_father, :class_name => 'Person', :foreign_key => 'father_id'
  has_many :children_of_mother, :class_name => 'Person', :foreign_key => 'mother_id'

  scope :children_for, lambda {|father_id, mother_id| where('father_id = ? AND mother_id = ?', father_id, mother_id) }
end

这个技巧可以让没有使用实例的孩子轻松获得:

Person.children_for father_id, mother_id

不是所述一般问题的解决方案(“has_many with many foreign keys”),但是,如果一个人可以是母亲或父亲,但不是两者,我会添加一个gender列并继续

  has_many :children_of_father, :class_name => 'Person', :foreign_key => 'father_id'
  has_many :children_of_mother, :class_name => 'Person', :foreign_key => 'mother_id'
  def children
    gender == "male" ? children_of_father : children_of_mother
  end

我对rails(3.2)中关联和(多个)外键的回答:如何在模型中描述它们,并编写迁移只适合你!

至于你的代码,这是我的修改

class Person < ActiveRecord::Base
  belongs_to :father, :class_name => 'Person'
  belongs_to :mother, :class_name => 'Person'
  has_many :children, ->(person) { unscope(where: :person_id).where("father_id = ? OR mother_id = ?", person.id, person.id) }, class_name: 'Person'
end

有问题吗?

我一直在寻找相同的功能,如果你不想返回一个数组而是一个ActiveRecord::AssociationRelation ,你可以使用<<而不是+ 参见ActiveRecord文档

class Person < ActiveRecord::Base
  belongs_to :father, :class_name => 'Person'
  belongs_to :mother, :class_name => 'Person'

  has_many :children_of_father, :class_name => 'Person', :foreign_key => 'father_id'
  has_many :children_of_mother, :class_name => 'Person', :foreign_key => 'mother_id'

  def children
     children_of_mother << children_of_father
  end
end

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM