为什么坚持? ActiveRecord :: Rollback后返回true?

时间:2014-01-17 00:40:44

标签: ruby-on-rails activerecord ruby-on-rails-4 simple-form

示例:

BillingProfile.transaction do
  if @billing_profile.save
    unless SomeService.do_something # returns false and rollback occurs
      raise ActiveRecord::Rollback
    end
  end
end

@billing_profile.persisted? # Still return true, despite rollback
@billing_profile.id # Is set, despite rollback

为什么@billing_profile的状态不会反映该记录已被回滚?

这是一个问题,因为在回滚后无法创建记录。

2 个答案:

答案 0 :(得分:3)

原来这是ActiveRecord(Rails 4)中的一个错误:https://github.com/rails/rails/issues/13744

现在已经修复了。

答案 1 :(得分:0)

我对交易如何运作感兴趣。您的具体方案在docs中说明。引用文档

  

事务调用可以嵌套。默认情况下,这会使所有数据库   嵌套事务块中的语句成为父项的一部分   交易。例如,以下行为可能会令人惊讶:

User.transaction do
  User.create(username: 'Kotori')
  User.transaction do
    User.create(username: 'Nemu')
    raise ActiveRecord::Rollback
  end
end
     

创造了“Kotori”和“Nemu”。 Reason是ActiveRecord :: Rollback   嵌套块中的异常不会发出ROLLBACK。既然这些   父块执行的事务块中捕获异常   没有看到它,真正的交易已经提交。

     

为了获得嵌套事务的ROLLBACK,您可能会要求   通过传递requires_new:true来实现真正的子事务。如果有的话   错了,数据库回滚到子事务的开头   没有回滚父事务。如果我们将它添加到   上一个例子:

User.transaction do
  User.create(username: 'Kotori')
  User.transaction(requires_new: true) do
    User.create(username: 'Nemu')
    raise ActiveRecord::Rollback
  end
end
     

仅创建“Kotori”。这适用于MySQL和PostgreSQL。 sqlite3的   版本> ='3.6.8'也支持它。

     

大多数数据库不支持真正的嵌套事务。在那个时间   写作,我们所知道的唯一支持true的数据库   嵌套事务,是MS-SQL。因此,Active Record   通过在MySQL和MySQL上使用保存点来模拟嵌套事务   PostgreSQL的。请参阅dev.mysql.com/doc/refman/5.6/en/savepoint.html   有关保存点的更多信息。