From 884af53be206504b2aabaa7014b8c2224123e3b1 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Thu, 13 Jun 2024 10:41:33 +0200 Subject: [PATCH] `ActiveRecord::Transaction#open?` returns false if the transaction is finalized Followup: https://github.com/rails/rails/pull/52104 --- activerecord/lib/active_record/transaction.rb | 6 +++-- activerecord/test/cases/transactions_test.rb | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/transaction.rb b/activerecord/lib/active_record/transaction.rb index 2977b68a7d..d2e6676234 100644 --- a/activerecord/lib/active_record/transaction.rb +++ b/activerecord/lib/active_record/transaction.rb @@ -94,12 +94,14 @@ def after_rollback(&block) @internal_transaction&.after_rollback(&block) end + # Returns true if the transaction exists and isn't finalized yet def open? - @internal_transaction&.open? + !closed? end + # Returns true if the transaction doesn't exists or is finalized (committed or rolled back) def closed? - !open? + @internal_transaction.nil? || @internal_transaction.state.finalized? end alias_method :blank?, :closed? diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index a01bf6e191..cbdf7319d0 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -12,6 +12,29 @@ require "models/cpk" module TransactionCallbacksTests + SomeError = Class.new(StandardError) + + def test_transaction_open? + assert_predicate Topic.current_transaction, :closed? + + committed_transaction = nil + Topic.transaction do + assert_predicate Topic.current_transaction, :open? + committed_transaction = Topic.current_transaction + end + assert_predicate committed_transaction, :closed? + + rolledback_transaction = nil + assert_raises SomeError do + Topic.transaction do + assert_predicate Topic.current_transaction, :open? + rolledback_transaction = Topic.current_transaction + raise SomeError + end + end + assert_predicate rolledback_transaction, :closed? + end + def test_after_all_transactions_commit called = 0 ActiveRecord.after_all_transactions_commit { called += 1 }