提交 e0a315b3 编写于 作者: R Ryuta Kamizono

Should take the record's state of first action in the transaction

If the same id's records are saved and/or destroyed in the transaction,
commit callbackes will only run for the first enrolled record.

https://github.com/rails/rails/blob/a023e2180093ebc517a642aaf21f3c7241c67657/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb#L115-L119

The regression #36132 is caused due to #35920 changed the enrollment
order that the first action's record will be enrolled to last in the
transaction.

We could not change the the enrollment order as long as someone depends
on the enrollment order.

Fixes #36132.
上级 c1ff1392
......@@ -333,7 +333,7 @@ def before_committed! # :nodoc:
# 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:
if should_run_callbacks && (destroyed? || persisted?)
if should_run_callbacks && trigger_transactional_callbacks?
@_committed_already_called = true
_run_commit_without_transaction_enrollment_callbacks
_run_commit_callbacks
......@@ -346,7 +346,7 @@ 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:
if should_run_callbacks
if should_run_callbacks && trigger_transactional_callbacks?
_run_rollback_callbacks
_run_rollback_without_transaction_enrollment_callbacks
end
......@@ -364,7 +364,9 @@ def rolledback!(force_restore_state: false, should_run_callbacks: true) #:nodoc:
def with_transaction_returning_status
status = nil
self.class.transaction do
unless has_transactional_callbacks?
if has_transactional_callbacks?
add_to_transaction
else
sync_with_transaction_state if @transaction_state&.finalized?
@transaction_state = self.class.connection.transaction_state
end
......@@ -372,11 +374,6 @@ def with_transaction_returning_status
status = yield
raise ActiveRecord::Rollback unless status
ensure
if has_transactional_callbacks? &&
(@_new_record_before_last_commit && !new_record? || _trigger_update_callback || _trigger_destroy_callback)
add_to_transaction
end
end
status
end
......@@ -460,6 +457,10 @@ def add_to_transaction
self.class.connection.add_transaction_record(self)
end
def trigger_transactional_callbacks?
@_new_record_before_last_commit && !new_record? || _trigger_update_callback || _trigger_destroy_callback
end
def has_transactional_callbacks?
!_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_before_commit_callbacks.empty?
end
......
......@@ -36,6 +36,8 @@ class TopicWithCallbacks < ActiveRecord::Base
has_many :replies, class_name: "ReplyWithCallbacks", foreign_key: "parent_id"
before_destroy { self.class.find(id).touch if persisted? }
before_commit { |record| record.do_before_commit(nil) }
after_commit { |record| record.do_after_commit(nil) }
after_save_commit { |record| record.do_after_commit(:save) }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册