2013-09-25 27 views
2

我有兩個型號:如何在一次交易中保存相關模型?

class Customer < ActiveRecord::Base 
    has_many :contacts 
end 

class Contact < ActiveRecord::Base 
    belongs_to :customer 
    validates :customer, presence: true 
end 

然後,在我的控制,我會希望能夠創造出既 「一」掃:

@customer = Customer.new 
@customer.contacts.build 
@customer.save 

此,失敗(不幸的翻譯對,它轉化爲 類似:聯繫人:客戶不能爲空)

@customer.errors.messages #=> :contacts=>["translation missing: en.activerecord.errors.models.customer.attributes.contacts.invalid"]} 

檢查時。模型的確,@customer.contacts.first.customernil。不知何故,這是有道理的,因爲@customer尚未保存 ,因此沒有id

如何建立這樣的關聯模型,然後保存/創建它們,使:

  • 如果一個非法,無模型被持久,
  • 錯誤可以在一個列表中,而讀出然後結合所有型號的 錯誤消息,
  • ,並保持我的代碼簡潔?
+0

我的第一個想法 - 如果您始終通過客戶創建聯繫人,請不要驗證客戶的存在。或者至少在那裏陳述一條if語句,並排除客戶是新記錄時的情況。 – Almaron

+0

在關係聲明中增加':inverse_of'。 – j03w

+0

@ j03w:inverse_of確實擺脫了驗證:這是解決方案。你可以補充說,所以我可以將其標記爲解決方案? – berkes

回答

2

rails api doc

如果你要修改的關聯(而不是從它剛讀)的交易,那麼它是設置一個好主意:inverse_of的選項源連接模型。這允許建立關聯的記錄,當它們被保存時它將自動創建適當的聯接模型記錄。 (見協會加入模式'上面的部分。)

所以只需添加:inverse_of到關係宣言(has_manybelongs_to等)將使active_record保存模型以正確的順序。

1
  • 是來到我的腦海裏的第一件事情 - 剛剛擺脫驗證。
  • 想到的第二件事 - 先保存客戶,然後建立聯繫。
  • 第三件事:在聲明關係時使用:inverse_of。也可以幫助。
1

您可以將新創建​​的相關模型保存在單個數據庫事務中,但不能使用單個方法調用save方法。一些ORM(例如LINQToSQL和實體框架)可以做到,但ActiveRecord不能。只需使用ActiveRecord::Base.transaction方法來確保兩個模型都保存或者不存在。更多的ActiveRecord這裏http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

+0

謝謝:我計劃在未來將所有這個建築物移到Builder類中。那麼'ActiveRecord :: Base.transaction'會派上用場。現在,我可以解決它,通過評論中提供的'inverse_of'來標記關係。 – berkes