2010-03-20 32 views
2

我有兩種型號:PersonAddress我想在交易中創建。也就是說,我想嘗試創建Person,如果成功,請創建相關的Address。我希望使用save語義(返回truefalse)而不是save!語義(提高或不提高ActiveRecord::StatementInvalid)。如何在ActiveRecord事務中保存(無感嘆號)語義?

這並不工作,因爲user.save不觸發事務回滾:

class Person 
    def save_with_address(address_options = {}) 
    transaction do 
     self.save 
     address = Address.build(address_options) 
     address.person = self 
     address.save 
    end 
    end 
end 

(更改self.save呼叫周圍的休息並沒有幫助的if self.save塊,因爲Person保存當Address一個失敗還是成功偶數)

這不起作用,因爲它提高了ActiveRecord::StatementInvalid異常出transaction塊不會觸發ActiveRecord::Rollback

class Person 
    def save_with_address(address_options = {}) 
    transaction do 
     save! 
     address = Address.build(address_options) 
     address.person = self 
     address.save! 
    end 
    end 
end 

Rails documentation具體警告不要捕捉ActiveRecord::StatementInvalidtransaction塊內。

我想我的第一個問題是:爲什麼不是這個交易區塊......在兩個保存上進行交易?

回答

5

這個怎麼樣?

class Person 
    def save_with_address(address_options = {}) 
    tx_error = false 
    transaction do 
     begin 
     self.save! 
     address = Address.build(address_options) 
     address.person = self 
     address.save! 
     rescue Exception => e 
     # add relevant error message to self using errors.add_to_base 
     raise ActiveRecord::Rollback 
     tx_error = true 
     end 
    end 
    return true unless tx_error 

    # now roll back the Person TX. 
    raise ActiveRecord::Rollback 
    return false 
    end 
end 

我不喜歡TX的實現方式。但這是你如何解決問題的方法。

+0

修復了根據需要返回true/false的代碼。 – 2010-03-20 04:10:37

+0

添加了額外的代碼來回滾Person模型的變化 – 2010-03-20 04:32:17

+0

我不確定第二個'ActiveRecord :: Rollback'在'transaction'塊的外面做了什麼。 – 2010-03-20 15:37:59

0

告訴ActiveRecord爲你做這件事。保存你的問題堆:

class Person < ActiveRecord::Base 
    belongs_to :address, :autosave => true 
end 

好的是,人的錯誤將包含地址'驗證錯誤,格式正確。

有關更多信息,請參閱AutosaveAssocation模塊。

+0

它實際上是'Person.has_many:addresses',我只需要至少一個,但是看起來'autosave'至少會給我'地址'上的驗證。我可能需要在零地址上添加某種自定義錯誤。 – 2010-03-20 15:07:15

+0

另外,就我所知,':autosave => true'在創建時不起作用,僅在更新時才起作用。具體來說,'Address'的'user_id'沒有被設置(因爲'User'還沒有),因此總是無效的。 – 2010-03-20 15:33:46