我有一个Family
类,其中包括mother_id
和father_id
。从家庭模式的角度来看,了解哪个父母是母亲,哪个父亲是重要的,但母亲和父亲拥有所有相同的属性(即数据库列)。所以理想情况下,我希望我的模型文件看起来像这样:has_one带有多个可能的外键列
class Resident < ActiveRecord::Base
has_one :family, :dependent => :nullify, :foreign_key => :father_id
has_one :family, :dependent => :nullify, :foreign_key => :mother_id
attr_accessible :email, :cell, :first_name, :last_name
end
class Family < ActiveRecord::Base
belongs_to :father, :class_name => 'Resident', :foreign_key => 'father_id'
belongs_to :mother, :class_name => 'Resident', :foreign_key => 'mother_id'
attr_accessible :address, :city, :state, :number_of_children
end
这是行不通的。 my_family.mother
和my_family.father
工作,所以Rails似乎很高兴与双belongs_to
。但是,my_dad.family == nil
,表明第二个has_one
重写第一个。这是合理的,否则,如果resident_id出现在mother_id和father_id列中,会发生什么情况? (虽然我计划添加模型级别验证以确保永不发生,但has_one
不会与验证方法进行交谈。)此外,my_dad.family = Family.new
是什么意思? ActiveRecord如何选择是否将my_dad.id
插入Family.mother_id
或Family.father_id
?
从this Stackoverflow question,我得到了主意,使用不同的名称,即has_one
线更改为:
has_one :wife_and_kids, :class_name => 'Family', :dependent => :nullify, :foreign_key => :father_id
has_one :husband_and_kids, :class_name => 'Family', :dependent => :nullify, :foreign_key => :mother_id
我的问题是:
1)是否有更好的方式来做到这一点?一个不同的数据库模式,也许?
2)是数据库级别的验证可以补充模型级验证,以确保my_dad.id
不能同时在mother_id
和father_id
栏显示?
3)你能想到比husband_and_kids
/wife_and_kids
更好的名字吗? (诚然不是一个编程的问题...)
编辑: 它发生在我加入一个家庭的getter:
def family
@family ||= self.wife_and_kids || self.husband_and_kids
end
after_save :reset_family
def reset_family
@family = nil
end
这使得语法更清洁(因为我真的不是一个风扇的[husband|wife]_and_kids
),没有造成任何歧义,因为没有设置。
我不明白为什么它会回答我的第二个问题。如果居民有类型'男性',但我尝试将其ID插入到Family.mother_id中,数据库将不知道它是无效的。 –
我想它间接地回答第二个问题,因为它使得明确的验证是不必要的。创建新记录时,如果限制自己仅实例化Mother对象或Father对象,则外键的含义不会有任何歧义。 Mother对象在family表中有一个外键:mother_id,并且这种方式无法与以下内容混淆:father_id – cdesrosiers
但是该验证在模型中,即在应用程序中。问题#2是关于数据库级的验证 - 如果将来有另一个应用程序需要连接到数据库会怎么样 - 我该如何强制未来应用程序的开发人员将无法将父亲放入mother_id列的错误? 当你运行rails生成model family mother_id:integer:uniq'时,rails会在模式文件中放入: 'add_index“family,[”mother_id“],:name =>”index_families_on_mother_id“,:unique => true' 我想要类似的验证,说没有mother_id列可以输入father_id列 –