diff options
Diffstat (limited to 'activerecord')
4 files changed, 28 insertions, 4 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 11440e30d4..3a1e4a4a88 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -77,6 +77,10 @@ module ActiveRecord @state.set_state(:committed) end + def before_commit_records + records.uniq.each(&:before_committed!) + end + def commit_records ite = records.uniq while record = ite.shift @@ -159,13 +163,15 @@ module ActiveRecord def commit_transaction inner_transaction = @stack.pop - inner_transaction.commit if current_transaction.joinable? + inner_transaction.commit inner_transaction.records.each do |r| r.add_to_transaction end else + inner_transaction.before_commit_records + inner_transaction.commit inner_transaction.commit_records end end diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index 44d587206d..a71f7a03ea 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -487,7 +487,7 @@ module ActiveRecord end def has_transactional_callbacks? # :nodoc: - !_rollback_callbacks.empty? || !_commit_callbacks.empty? + !_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_before_commit_callbacks.empty? end # Updates the attributes on this particular ActiveRecord object so that diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index e6580c9930..598defce50 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -7,6 +7,8 @@ module ActiveRecord included do define_callbacks :commit, :rollback, + :before_commit, + :before_commit_without_transaction_enrollment, :commit_without_transaction_enrollment, :rollback_without_transaction_enrollment, scope: [:kind, :name] @@ -208,6 +210,11 @@ module ActiveRecord connection.transaction(options, &block) end + def before_commit(*args, &block) # :nodoc: + set_options_for_callbacks!(args) + set_callback(:before_commit, :before, *args, &block) + end + # This callback is called after a record has been created, updated, or destroyed. # # You can specify that the callback should only be fired by a certain action with @@ -235,6 +242,11 @@ module ActiveRecord set_callback(:rollback, :after, *args, &block) end + def before_commit_without_transaction_enrollment(*args, &block) # :nodoc: + set_options_for_callbacks!(args) + set_callback(:before_commit_without_transaction_enrollment, :before, *args, &block) + end + def after_commit_without_transaction_enrollment(*args, &block) # :nodoc: set_options_for_callbacks!(args) set_callback(:commit_without_transaction_enrollment, :after, *args, &block) @@ -308,6 +320,11 @@ module ActiveRecord clear_transaction_record_state end + def before_committed! # :nodoc: + _run_before_commit_without_transaction_enrollment_callbacks + _run_before_commit_callbacks + end + # Call the +after_commit+ callbacks. # # Ensure that it is not called if the object was never persisted (failed create), diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb index 60b0fd4112..5cac9ff84b 100644 --- a/activerecord/test/cases/transaction_callbacks_test.rb +++ b/activerecord/test/cases/transaction_callbacks_test.rb @@ -407,7 +407,8 @@ class TransactionEnrollmentCallbacksTest < ActiveRecord::TestCase class TopicWithoutTransactionalEnrollmentCallbacks < ActiveRecord::Base self.table_name = :topics - after_commit_without_transaction_enrollment { |r| r.history << :commit } + before_commit_without_transaction_enrollment { |r| r.history << :before_commit } + after_commit_without_transaction_enrollment { |r| r.history << :after_commit } after_rollback_without_transaction_enrollment { |r| r.history << :rollback } def history @@ -435,7 +436,7 @@ class TransactionEnrollmentCallbacksTest < ActiveRecord::TestCase end @topic.class.connection.add_transaction_record(@topic) end - assert_equal [:commit], @topic.history + assert_equal [:before_commit, :after_commit], @topic.history end def test_rollback_dont_enroll_transaction |