Bubbling Up Nested-transaction Failures with ActiveRecord

I have a method in a service object that composes operations that should be wrapped in a transaction. Some of these operations are also wrapped in transactions. For example:

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

I need any nested failures to bubble up all the way to the top, but I'm not sure how to make that happen, and the ActiveRecord docs on nested transactions don't seem to offer a solution. From the docs:

# 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

Answers


Here's how you could get failures in your nested transactions to bubble up:

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

Basically, you have to raise an error in your top-level transaction for it to rollback too. To do that, you raise an error if the nested transaction returns a falsey value(nil) or a truthy value.

Hope that helps!


Another easier approach, you can raise an CustomError < StandardError. Unlike ActiveRecord::Rollback, Error will bubble up through parent transactions. You can handle it wherever required. All other inner transactions will be rolled back.

Try the below template.

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

Throwing a custom error is always a good option in case of nested transactions. Please find more detail on nested-transations-in-rails .


Need Your Help

Invalid Pointer Operation - Delphi XE

delphi debugging exception delphi-xe

I can't seem to figure this one out. My program compiles and runs successfully, but during debugging only it pops up a message box saying "Invalid Pointer Operation" when shutting the program down. I