rspecruby-on-rails-4database-cleaner

Any reason a TX in Rails should not have requires_new: true


Related to this question: custom transaction doesn't work with database_cleaner in rspec

Is there any place one would not want to start a TX with requires_new? (which does nested TX)

ModelObject.transaction(requires_new: true)

If that's the case, should this have been the default.

BTW, this is a reason that an rspec test with a rollback will fail when the normal execution path of the code succeeds, when using the default transaction strategy.

Here's my DatabaseCleaner setup. Running Rails 4.

RSpec.configure do |config|
  config.add_setting(:seed_tables)
  config.seed_tables = %w(global_options shoot_types)

  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation, except: config.seed_tables)
  end

  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end

  config.before(:each, js: true) do
    DatabaseCleaner.strategy = :truncation, {except: config.seed_tables}
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end

end

Solution

  • In order to get a ROLLBACK for the nested transaction you may ask for a real sub-transaction by passing requires_new: true. If anything goes wrong, the database rolls back to the beginning of the sub-transaction without rolling back the parent transaction. If we add it to the previous example:

    Most databases don’t support true nested transactions. At the time of writing, the only database that we’re aware of that supports true nested transactions, is MS-SQL. Because of this, Active Record emulates nested transactions by using savepoints on MySQL and PostgreSQL. See dev.mysql.com/doc/refman/5.6/en/savepoint.html for more information about savepoints.

    http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html