Skip to content

Commit 00554bf

Browse files
committed
Allow to pass transaction options to the in_transaction helper
This allows to use it as a replacement for the `ActiveRecord::Base.transaction`
1 parent 9e32dec commit 00554bf

File tree

2 files changed

+26
-5
lines changed

2 files changed

+26
-5
lines changed

lib/after_commit_everywhere.rb

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,15 +134,21 @@ def in_transaction?(connection = nil)
134134

135135
# Makes sure the provided block runs in a transaction. If we are not currently in a transaction, a new transaction is started.
136136
#
137+
# It mimics the ActiveRecord's +transaction+ method's API and actually uses it under the hood.
138+
#
139+
# However, the main difference is that it doesn't swallow +ActiveRecord::Rollback+ exception in case when there is no transaction open.
140+
#
141+
# @see https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/DatabaseStatements.html#method-i-transaction
142+
#
137143
# @param connection [ActiveRecord::ConnectionAdapters::AbstractAdapter] Database connection to operate in. Defaults to +ActiveRecord::Base.connection+
144+
# @param requires_new [Boolean] Forces creation of new subtransaction (savepoint) even if transaction is already opened.
145+
# @param new_tx_options [Hash<Symbol, void>] Options to be passed to +connection.transaction+ on new transaction creation
138146
# @return void
139-
def in_transaction(connection = nil)
140-
connection ||= default_connection
141-
142-
if in_transaction?(connection)
147+
def in_transaction(connection = default_connection, requires_new: false, **new_tx_options)
148+
if in_transaction?(connection) && !requires_new
143149
yield
144150
else
145-
connection.transaction { yield }
151+
connection.transaction(requires_new: requires_new, **new_tx_options) { yield }
146152
end
147153
end
148154

spec/after_commit_everywhere_spec.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,21 @@
550550
end
551551
end
552552

553+
it "runs new transaction even inside existing transaction if requires_new is true" do
554+
outer_handler, inner_handler = spy("outter"), spy("inner")
555+
expect(ActiveRecord::Base.connection.transaction_open?).to be_falsey
556+
ActiveRecord::Base.transaction do
557+
expect(ActiveRecord::Base.connection.transaction_open?).to be_truthy
558+
described_class.after_commit { outer_handler.call }
559+
receiver.in_transaction(requires_new: true) do
560+
receiver.after_commit { inner_handler.call }
561+
raise ActiveRecord::Rollback
562+
end
563+
end
564+
expect(outer_handler).to have_received(:call)
565+
expect(inner_handler).not_to have_received(:call)
566+
end
567+
553568
context "when rolling back, the rollback propogates to the parent transaction block" do
554569
subject { receiver.after_rollback { handler.call } }
555570

0 commit comments

Comments
 (0)