aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/transaction_callbacks_test.rb
diff options
context:
space:
mode:
authorJeremy Kemper <jeremy@bitsweat.net>2010-06-08 16:59:06 -0400
committerJeremy Kemper <jeremy@bitsweat.net>2010-06-08 17:05:29 -0400
commitb07073924002fd56ac5b63b24cb9318b3dee45c4 (patch)
treeab78a786c1456337c948081dd042639302335610 /activerecord/test/cases/transaction_callbacks_test.rb
parent87cc3d556948f4cb644091c98969c03e319c864e (diff)
downloadrails-b07073924002fd56ac5b63b24cb9318b3dee45c4.tar.gz
rails-b07073924002fd56ac5b63b24cb9318b3dee45c4.tar.bz2
rails-b07073924002fd56ac5b63b24cb9318b3dee45c4.zip
Revert "Temporarily revert "Update after_commit and after_rollback docs and tests to use new style API with an :on options instead of on_* suffix." and "Add after_commit and after_rollback callbacks to ActiveRecord that are called after transactions either commit or rollback on all records saved or destroyed in the transaction.""
This reverts commit 1b2941cba1165b0721f57524645fe378bee2a950. [#2991]
Diffstat (limited to 'activerecord/test/cases/transaction_callbacks_test.rb')
-rw-r--r--activerecord/test/cases/transaction_callbacks_test.rb240
1 files changed, 240 insertions, 0 deletions
diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb
new file mode 100644
index 0000000000..ebc16653cb
--- /dev/null
+++ b/activerecord/test/cases/transaction_callbacks_test.rb
@@ -0,0 +1,240 @@
+require "cases/helper"
+require 'models/topic'
+require 'models/reply'
+
+class TransactionCallbacksTest < ActiveRecord::TestCase
+ self.use_transactional_fixtures = false
+ fixtures :topics
+
+ class TopicWithCallbacks < ActiveRecord::Base
+ set_table_name :topics
+
+ after_commit{|record| record.send(:do_after_commit, nil)}
+ after_commit(:on => :create){|record| record.send(:do_after_commit, :create)}
+ after_commit(:on => :update){|record| record.send(:do_after_commit, :update)}
+ after_commit(:on => :destroy){|record| record.send(:do_after_commit, :destroy)}
+ after_rollback{|record| record.send(:do_after_rollback, nil)}
+ after_rollback(:on => :create){|record| record.send(:do_after_rollback, :create)}
+ after_rollback(:on => :update){|record| record.send(:do_after_rollback, :update)}
+ after_rollback(:on => :destroy){|record| record.send(:do_after_rollback, :destroy)}
+
+ def history
+ @history ||= []
+ end
+
+ def after_commit_block(on = nil, &block)
+ @after_commit ||= {}
+ @after_commit[on] ||= []
+ @after_commit[on] << block
+ end
+
+ def after_rollback_block(on = nil, &block)
+ @after_rollback ||= {}
+ @after_rollback[on] ||= []
+ @after_rollback[on] << block
+ end
+
+ def do_after_commit(on)
+ blocks = @after_commit[on] if defined?(@after_commit)
+ blocks.each{|b| b.call(self)} if blocks
+ end
+
+ def do_after_rollback(on)
+ blocks = @after_rollback[on] if defined?(@after_rollback)
+ blocks.each{|b| b.call(self)} if blocks
+ end
+ end
+
+ def setup
+ @first, @second = TopicWithCallbacks.find(1, 3).sort_by { |t| t.id }
+ end
+
+ def test_call_after_commit_after_transaction_commits
+ @first.after_commit_block{|r| r.history << :after_commit}
+ @first.after_rollback_block{|r| r.history << :after_rollback}
+
+ @first.save!
+ assert_equal [:after_commit], @first.history
+ end
+
+ def test_only_call_after_commit_on_update_after_transaction_commits_for_existing_record
+ @first.after_commit_block(:create){|r| r.history << :commit_on_create}
+ @first.after_commit_block(:update){|r| r.history << :commit_on_update}
+ @first.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
+ @first.after_rollback_block(:create){|r| r.history << :rollback_on_create}
+ @first.after_rollback_block(:update){|r| r.history << :rollback_on_update}
+ @first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
+
+ @first.save!
+ assert_equal [:commit_on_update], @first.history
+ end
+
+ def test_only_call_after_commit_on_destroy_after_transaction_commits_for_destroyed_record
+ @first.after_commit_block(:create){|r| r.history << :commit_on_create}
+ @first.after_commit_block(:update){|r| r.history << :commit_on_update}
+ @first.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
+ @first.after_rollback_block(:create){|r| r.history << :rollback_on_create}
+ @first.after_rollback_block(:update){|r| r.history << :rollback_on_update}
+ @first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
+
+ @first.destroy
+ assert_equal [:commit_on_destroy], @first.history
+ end
+
+ def test_only_call_after_commit_on_create_after_transaction_commits_for_new_record
+ @new_record = TopicWithCallbacks.new(:title => "New topic", :written_on => Date.today)
+ @new_record.after_commit_block(:create){|r| r.history << :commit_on_create}
+ @new_record.after_commit_block(:update){|r| r.history << :commit_on_update}
+ @new_record.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
+ @new_record.after_rollback_block(:create){|r| r.history << :rollback_on_create}
+ @new_record.after_rollback_block(:update){|r| r.history << :rollback_on_update}
+ @new_record.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
+
+ @new_record.save!
+ assert_equal [:commit_on_create], @new_record.history
+ end
+
+ def test_call_after_rollback_after_transaction_rollsback
+ @first.after_commit_block{|r| r.history << :after_commit}
+ @first.after_rollback_block{|r| r.history << :after_rollback}
+
+ Topic.transaction do
+ @first.save!
+ raise ActiveRecord::Rollback
+ end
+
+ assert_equal [:after_rollback], @first.history
+ end
+
+ def test_only_call_after_rollback_on_update_after_transaction_rollsback_for_existing_record
+ @first.after_commit_block(:create){|r| r.history << :commit_on_create}
+ @first.after_commit_block(:update){|r| r.history << :commit_on_update}
+ @first.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
+ @first.after_rollback_block(:create){|r| r.history << :rollback_on_create}
+ @first.after_rollback_block(:update){|r| r.history << :rollback_on_update}
+ @first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
+
+ Topic.transaction do
+ @first.save!
+ raise ActiveRecord::Rollback
+ end
+
+ assert_equal [:rollback_on_update], @first.history
+ end
+
+ def test_only_call_after_rollback_on_destroy_after_transaction_rollsback_for_destroyed_record
+ @first.after_commit_block(:create){|r| r.history << :commit_on_create}
+ @first.after_commit_block(:update){|r| r.history << :commit_on_update}
+ @first.after_commit_block(:destroy){|r| r.history << :commit_on_update}
+ @first.after_rollback_block(:create){|r| r.history << :rollback_on_create}
+ @first.after_rollback_block(:update){|r| r.history << :rollback_on_update}
+ @first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
+
+ Topic.transaction do
+ @first.destroy
+ raise ActiveRecord::Rollback
+ end
+
+ assert_equal [:rollback_on_destroy], @first.history
+ end
+
+ def test_only_call_after_rollback_on_create_after_transaction_rollsback_for_new_record
+ @new_record = TopicWithCallbacks.new(:title => "New topic", :written_on => Date.today)
+ @new_record.after_commit_block(:create){|r| r.history << :commit_on_create}
+ @new_record.after_commit_block(:update){|r| r.history << :commit_on_update}
+ @new_record.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
+ @new_record.after_rollback_block(:create){|r| r.history << :rollback_on_create}
+ @new_record.after_rollback_block(:update){|r| r.history << :rollback_on_update}
+ @new_record.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
+
+ Topic.transaction do
+ @new_record.save!
+ raise ActiveRecord::Rollback
+ end
+
+ assert_equal [:rollback_on_create], @new_record.history
+ end
+
+ def test_call_after_rollback_when_commit_fails
+ @first.connection.class.send(:alias_method, :real_method_commit_db_transaction, :commit_db_transaction)
+ begin
+ @first.connection.class.class_eval do
+ def commit_db_transaction; raise "boom!"; end
+ end
+
+ @first.after_commit_block{|r| r.history << :after_commit}
+ @first.after_rollback_block{|r| r.history << :after_rollback}
+
+ assert !@first.save rescue nil
+ assert_equal [:after_rollback], @first.history
+ ensure
+ @first.connection.class.send(:remove_method, :commit_db_transaction)
+ @first.connection.class.send(:alias_method, :commit_db_transaction, :real_method_commit_db_transaction)
+ end
+ end
+
+ def test_only_call_after_rollback_on_records_rolled_back_to_a_savepoint
+ def @first.rollbacks(i=0); @rollbacks ||= 0; @rollbacks += i if i; end
+ def @first.commits(i=0); @commits ||= 0; @commits += i if i; end
+ @first.after_rollback_block{|r| r.rollbacks(1)}
+ @first.after_commit_block{|r| r.commits(1)}
+
+ def @second.rollbacks(i=0); @rollbacks ||= 0; @rollbacks += i if i; end
+ def @second.commits(i=0); @commits ||= 0; @commits += i if i; end
+ @second.after_rollback_block{|r| r.rollbacks(1)}
+ @second.after_commit_block{|r| r.commits(1)}
+
+ Topic.transaction do
+ @first.save!
+ Topic.transaction(:requires_new => true) do
+ @second.save!
+ raise ActiveRecord::Rollback
+ end
+ end
+
+ assert_equal 1, @first.commits
+ assert_equal 0, @first.rollbacks
+ assert_equal 0, @second.commits
+ assert_equal 1, @second.rollbacks
+ end
+
+ def test_only_call_after_rollback_on_records_rolled_back_to_a_savepoint_when_release_savepoint_fails
+ def @first.rollbacks(i=0); @rollbacks ||= 0; @rollbacks += i if i; end
+ def @first.commits(i=0); @commits ||= 0; @commits += i if i; end
+
+ @first.after_rollback_block{|r| r.rollbacks(1)}
+ @first.after_commit_block{|r| r.commits(1)}
+
+ Topic.transaction do
+ @first.save
+ Topic.transaction(:requires_new => true) do
+ @first.save!
+ raise ActiveRecord::Rollback
+ end
+ Topic.transaction(:requires_new => true) do
+ @first.save!
+ raise ActiveRecord::Rollback
+ end
+ end
+
+ assert_equal 1, @first.commits
+ assert_equal 2, @first.rollbacks
+ end
+
+ def test_after_transaction_callbacks_should_not_raise_errors
+ def @first.last_after_transaction_error=(e); @last_transaction_error = e; end
+ def @first.last_after_transaction_error; @last_transaction_error; end
+ @first.after_commit_block{|r| r.last_after_transaction_error = :commit; raise "fail!";}
+ @first.after_rollback_block{|r| r.last_after_transaction_error = :rollback; raise "fail!";}
+
+ @first.save!
+ assert_equal :commit, @first.last_after_transaction_error
+
+ Topic.transaction do
+ @first.save!
+ raise ActiveRecord::Rollback
+ end
+
+ assert_equal :rollback, @first.last_after_transaction_error
+ end
+end