我有一個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列 –