2010-07-16 79 views
0

我很難搞清楚如何最好地建模我的數據。我有以下兩種模式在我的Rails應用程序:Rails/ActiveRecord:has_one,belongs_to和before_create

class Foo < ActiveRecord::Base 
    belongs_to :active_bar, :class_name => 'Bar' 
    accepts_nested_attributes_for :active_bar 

    before_create do |f| 
    f.active_bar.foo = f 

    # Causes stack overflow! 
    f.active_bar.save! 
    end 
end 

class Bar < ActiveRecord::Base 
    belongs_to :foo 
end 

test 'create with nested attributes' do 
    f = Foo.create!(:name => 'foo-name', :active_bar_attributes => {:name => 'bar-name'}) 
    assert_equal 'foo-name', f.name 
    assert_equal 'bar-name', f.active_bar.name 
    assert_equal f, f.active_bar.foo 

    f_id = f.to_param 

    retrieved_f = Foo.find_by_id!(f_id) 
    assert_equal retrieved_f, retrieved_f.active_bar.foo 
end 

什麼你可能覺得很奇怪是自反belongs_to關係,我試圖建模。我的計劃是,最終,Foo將有許多Bar的實例,而一個實例將被視爲「活動」。因此,我使用active_bar來引用此活動實例。此代碼的問題是,我需要將Bar中的foo屬性設置回父代Foo實例,我無法弄清楚最好的做法(save!調用before_create最終會遞歸併溢出堆棧)或者即使這是對這種類型的關係建模的最乾淨的方式。

本質上我試圖模擬一個用戶(相當於Foo)誰擁有多個電子郵件地址(相當於Bar)與其中一個電子郵件地址標記爲用戶的主要地址。

有什麼建議嗎?

+0

我想我會將'before_create'中的代碼移動到'after_create'中代替。這似乎工作。然而,我仍然不完全滿意於模擬的關係。 – 2010-07-16 18:10:51

回答

2

我只是在用戶和EmailAddress的方面迴應,如果這與你沒關係;)

在用戶模式確實應該has_many :email_addresseshas_one :active_email, :class_name => 'EmailAddress',正如你正確識別,accepts_nested_attributes_for :email_addresses

那麼EmailAddress模型當然應該有belongs_to :User

除了這些,我認爲你是過度思考的東西。然後,在創建用戶的表單中,允許他們輸入任意數量的電子郵件地址,並讓他們首先放入「活動」電子郵件,或者進行某種切換以表示哪個電子郵件地址是其主要地址。

編輯:至於before_create語句,我認爲它只需要一個簡單的驗證,主要電子郵件地址已被給予/標記(如果它是必要的,他們首先指定一個電子郵件地址)。

如果這不能滿足您需要的功能,請發表評論。我會盡力幫助更多。

+0

感謝您的提示!當我有機會時,我會嘗試一下。 - 理查德 – 2010-07-21 01:42:14

+0

我有同樣的問題。 「active_email_id」的實際值存儲在哪裏?不應該把'has_one'當成rail_ terms來使用 - 雖然英文看起來很糟糕。 – KDM 2014-10-08 09:23:02