【问题标题】:Bubbling Up Nested-transaction Failures with ActiveRecord使用 ActiveRecord 冒泡嵌套事务失败
【发布时间】:2017-03-30 07:32:28
【问题描述】:

我在服务对象中有一个方法,该方法组成了应该包装在事务中的操作。其中一些操作也包含在事务中。例如:

class PostCreator
   def create
      ActiveRecord::Base.transaction do
        post.do_this
        post.do_that
        user.do_more(post, other_stuff)
      end
   end
 end

 def Post
   def do_this
     transaction do; ...; end
   end
 end

我需要任何嵌套故障一直冒泡到顶部,但我不确定如何实现,nested transactions 上的 ActiveRecord 文档似乎没有提供解决方案。来自文档:

# Standard nesting

User.transaction do
  User.create(username: 'Kotori')
  User.transaction do
    User.create(username: 'Nemu')
    raise ActiveRecord::Rollback    #  This won't bubble up:
                                    #  _Both_ users will still be created.
  end
end

# Nesting with `requires_new: true` on the nested transaction

User.transaction do
  User.create(username: 'Kotori')
  User.transaction(requires_new: true) do
    User.create(username: 'Nemu')
    raise ActiveRecord::Rollback    #  This won't bubble up either
                                    #  "Kotori" will still be created.
  end
end

【问题讨论】:

  • 这是一个很好的问题。我经常看到一个方法有时被自己调用,所以它的内容被包装在一个事务中,但有时是从另一个事务内部调用的。我认为如果 ActiveRecord 在 :requires_new 未启用时默认冒泡错误会更好(因为嵌套块是父事务的一部分)。

标签: ruby-on-rails activerecord


【解决方案1】:

以下是如何让嵌套事务中的失败冒泡:

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

基本上,您必须在顶级事务中引发错误才能使其回滚。为此,如果嵌套事务返回虚假值(nil)或真实值,则会引发错误。

希望有帮助!

【讨论】:

    【解决方案2】:

    另一种更简单的方法,您可以引发 CustomError

    试试下面的模板。

    ActiveRecord::Base.transacton do
        ActiveRecord::Base.transacton do
            raise StandardError.new
        end
    end
    

    【讨论】:

    • 这样更简单更干净。
    【解决方案3】:

    在嵌套事务的情况下,抛出自定义错误始终是一个不错的选择。请在nested-transations-in-rails 上找到更多详细信息。

    【讨论】:

    • 如果你链接到你自己的博客或类似的东西,你需要披露。一个简单的 "my" 就足够了。此外,这看起来确实有点薄。你能举一个具体的例子来支持这个建议吗?
    猜你喜欢
    • 2014-07-26
    • 2012-12-18
    • 2018-08-24
    • 1970-01-01
    • 2015-12-10
    • 1970-01-01
    • 2018-09-06
    • 2014-08-26
    • 1970-01-01
    相关资源
    最近更新 更多