2011-09-03 27 views
11

假設我有這樣的:如何將現有記錄添加到has_many,而不立即保存到數據庫?

class Pirate < ActiveRecord::Base 
    has_many :parrots 
    validates_presence_of :name 
end 

class Parrot < ActiveRecord::Base 
    belongs_to :pirate 
end 

而且我有現有的海盜和鸚鵡與IDS 1〜10現在,我想這樣做:

p = Pirate.first 
p.name = nil 
p.parrot_ids = [1,2,3] 
p.save if p.valid? 

因爲海盜對象無效(它缺少名稱)我不希望它被保存。但是,鸚鵡現在已經與盜版聯繫在一起,並且它已經在數據庫中提交了。

如何分配鸚鵡,但只有在p.save成功後才能將鏈接保存到數據庫中?也就是說,如何在一次交易中將海盜和與鸚鵡的鏈接保存起來?

回答

1

你可以重新安排你的操作了一下:「如果p.valid」

p = Pirate.first 
p.name = nil 
if p.save 
    p.parrot_ids = [1,2,3] 
end 

注意有沒有必要在p.save之後;因爲有效?通過保存調用,確定是否嘗試將數據寫入數據庫。

如果您的鸚鵡不是預先存在的,您可以使用p.parrots.build(attributes = {...})來創建新的鸚鵡,這些鸚鵡在保存海盜父級之前不會保存。

請參閱ActiveRecord::Associations::ClassMethods documentation中的未保存對象和關聯部分。

+0

嗨,肯,我想讓鸚鵡參與驗證。我有:parrot_ids的質量分配。如果由於用戶試圖在鸚鵡中進行破解而導致驗證失敗,則他們不允許鏈接到該鏈接,則p.save應該失敗,此後,p.parrots應返回用戶嘗試的鸚鵡。 –

1

不幸的是,Rails的非常多建這樣的現有對象;如果對象已經存在,並且您與其關聯關聯,則始終會觸發更新。如果您有能力使用KenB提到的.build選項,那麼這是解決此問題的一種方法。但是,除了這一點,我現在只能想到一個辦法來處理這個問題。在交易中包裹整個操作,如下所示:

Pirate.transaction do 
    p = Pirate.first 
    p.name = nil 
    p.parrot_ids = [1,2,3] 

    if !p.save # Performing save in this manner will return false if validations fail (ie same as your p.valid?) 
     raise ActiveRecord::Rollback # should rollback anything executing within this transaction block 
    end 
end 

讓我知道這是否有幫助,如果沒有,請致歉。

+0

出於某種原因,我只是注意到這個問題已經超過兩歲了。對於死靈問題抱歉(假設它不再相關)。 –

相關問題