We already learn how transactions work inside a Ruby on Rails world and how to use transaction callbacks in order to add some useful features to our app. This time we would dig into nested transactions.

Creating nested transactions

Since transactions are just Ruby blocks, it’s easy to nest one transaction into other:

Post.transaction do
  Post.create!(title: 'Playing football')
  Post.transaction do
    Post.create!(title: 'Swimming')
  end
end

Rollback nested transaction

We have our transaction so now we may want to rollback a nested transaction. You may be surprised but this code would not work:

Post.transaction do
  Post.create!(title: 'Playing football')
  Post.transaction do
    Post.create!(title: 'Swimming')
    raise ActiveRecord::Rollback
  end
end

To make this code works you have to ask for a real sub-transaction otherwise it would not revert our creation. In order to do this we have to pass requires_new: true option - this would work in PostgreSQL, MySQL and SQLite from 3.6.8 version.

Post.transaction do
  Post.create!(title: 'Playing football')
  Post.transaction(requires_new: true) do
    Post.create!(title: 'Swimming')
    raise ActiveRecord::Rollback
  end
end

Want to receive useful tips, information about new Ruby gems and articles on a daily basis? Make sure you follow me and say hello!

Further information

Active Record emulates nested transactions by using savepoints on MySQL and PostgreSQL and only MS-SQL supports true nested transactions. You can read more about savepoints here - http://dev.mysql.com/doc/refman/5.7/en/savepoint.html

Want to become a better Rails developer?
Download for free the Introduction Rails patterns book and dive into the world of refactoring and easy-testable Ruby code today.
Join over 1,000 developers already subscribed to my newsletter and download the book. You can unsubscribe anytime:

Subscribe and get the book!