Testing after_commit/after_transaction with Rspec

Rails 3 has a neat after_commit hook that can be used to make sure that certain tasks are only fired after the entire transaction is committed to the database. For example you may be creating a user record and some associated records (like has_one user setting)and you might send an email in after_create callback. However if a child record is not saved and the transaction is rolled back, the user record will be deleted but the email would have already gone. The same applies for firing resque jobs too (as talked about in the FAQ).

The solution is to use the after_commit hook or a plugin like ar_after_transaction. The problem is that the after_commit callback is never fired in rspec if you are using transactional fixtures. One solution is to keep track of transactions and fake a callback as discussed in this blog post. However I had some issues with this approach. For instance even when defining callbacks on :create they were getting fired on every save.

Another solution is to switch off transactional fixtures and use database cleaner to clean the database. The :truncation strategy is a bit slow but you can use :deletion strategy. Here is how your spec_helper.rb file should look like after the change

blog comments powered by Disqus