2010-03-20 34 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