相对较新的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个外键一起使用,或者根据对象的性别更改外键?或者还有其他/更好的方式吗?
谢谢!
答案 0 :(得分:43)
在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
答案 1 :(得分:16)
要改进Kenzie的答案,您可以通过定义Person#children
来实现ActiveRecord关系:
def children
children_of_mother.merge(children_of_father)
end
有关详细信息,请参阅this answer
答案 2 :(得分:9)
在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
答案 3 :(得分:8)
我相信你可以使用: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
下班后我会确认并编辑这个答案; )
答案 4 :(得分:4)
我更喜欢使用范围来解决这个问题。像这样:
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
答案 5 :(得分:3)
不是所述一般问题的解决方案(&#34; has_many有多个外键&#34;),但是,如果某人可以是母亲或父亲,但不是两者,我会添加{ {1}}列,然后选择
gender
答案 6 :(得分:3)
至于你的代码,这是我的修改
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
那么有问题吗?
答案 7 :(得分:2)
我一直在寻找相同的功能,如果您不希望返回一个数组而不是ActiveRecord::AssociationRelation
,则可以使用<<
代替+
。
(See the ActiveRecord documentation)
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