提交 4a1bb9d0 编写于 作者: A Arthur Neves

Add transaction callbacks that wont enroll to the transaction.

Add after_commit_without_transaction_enrollment and
after_rollback_without_transaction_enrollment private callbacks so we
can create after_commit and after_rollback callbacks without having the
records automatic enrolled in the transaction.

[fixes #18904]
上级 62133326
......@@ -7,6 +7,8 @@ module Transactions
included do
define_callbacks :commit, :rollback,
:commit_without_transaction_enrollment,
:rollback_without_transaction_enrollment,
scope: [:kind, :name]
end
......@@ -233,6 +235,16 @@ def after_rollback(*args, &block)
set_callback(:rollback, :after, *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)
end
def after_rollback_without_transaction_enrollment(*args, &block) # :nodoc:
set_options_for_callbacks!(args)
set_callback(:rollback_without_transaction_enrollment, :after, *args, &block)
end
def raise_in_transactional_callbacks
ActiveSupport::Deprecation.warn('ActiveRecord::Base.raise_in_transactional_callbacks is deprecated and will be removed without replacement.')
true
......@@ -301,7 +313,10 @@ def rollback_active_record_state!
# Ensure that it is not called if the object was never persisted (failed create),
# but call it after the commit of a destroyed object.
def committed!(should_run_callbacks: true) #:nodoc:
_run_commit_callbacks if should_run_callbacks && destroyed? || persisted?
if should_run_callbacks && destroyed? || persisted?
_run_commit_without_transaction_enrollment_callbacks
_run_commit_callbacks
end
ensure
force_clear_transaction_record_state
end
......@@ -309,7 +324,10 @@ def committed!(should_run_callbacks: true) #:nodoc:
# Call the +after_rollback+ callbacks. The +force_restore_state+ argument indicates if the record
# state should be rolled back to the beginning or just to the last savepoint.
def rolledback!(force_restore_state: false, should_run_callbacks: true) #:nodoc:
_run_rollback_callbacks if should_run_callbacks
if should_run_callbacks
_run_rollback_without_transaction_enrollment_callbacks
_run_rollback_callbacks
end
ensure
restore_transaction_record_state(force_restore_state)
clear_transaction_record_state
......
......@@ -400,3 +400,62 @@ def test_after_commit_on_multiple_actions
assert_equal [:update_and_destroy, :create_and_destroy], topic.history
end
end
class TransactionEnrollmentCallbacksTest < ActiveRecord::TestCase
class TopicWithoutTransactionalEnrollmentCallbacks < ActiveRecord::Base
self.table_name = :topics
after_commit_without_transaction_enrollment { |r| r.history << :commit }
after_rollback_without_transaction_enrollment { |r| r.history << :rollback }
def history
@history ||= []
end
end
def setup
@topic = TopicWithoutTransactionalEnrollmentCallbacks.create!
end
def test_commit_dont_enroll_transaction
@topic.transaction do
@topic.content = 'foo'
@topic.save!
end
assert @topic.history.empty?
end
def test_commit_enrollment_transaction_when_call_add
@topic.transaction do
2.times do
@topic.content = 'foo'
@topic.save!
end
@topic.class.connection.add_transaction_record(@topic)
end
assert_equal [:commit], @topic.history
end
def test_rollback_dont_enroll_transaction
@topic.transaction do
@topic.content = 'foo'
@topic.save!
raise ActiveRecord::Rollback
end
assert @topic.history.empty?
end
def test_rollback_enrollment_transaction_when_call_add
@topic.transaction do
2.times do
@topic.content = 'foo'
@topic.save!
end
@topic.class.connection.add_transaction_record(@topic)
raise ActiveRecord::Rollback
end
assert_equal [:rollback], @topic.history
end
end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册