Rails transactions – nested transactions

Ruby on Rails / Active Record

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

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