This is my first post, so bear with me if I am missing something here.
Recently, I found that I wanted to access the current transaction to a callback after commit; not a model-level but transaction-level itself.
Using ActiveRecord you can do:
ActiveRecord::Base.transaction do |tx|
# Some logic here
tx.after_commit do
# some logic here
end
end
However, even though we can do transactions with dry-operation using the right extension, it does not allow to access the transaction for such behavior.
class CreateAppointOperation < Dry::Operation
include Dry::Operation::Extensions::ActiveRecord
def call
transaction do |tx|
service = step find_service
client = step find_or_create_client
appointment = step create_appointment(validated_params)
# Accesing tx is not possible
# We could probably access through current_transaction from ActiveRecord itself
# It would just be much cleaner to have it here
tx.after_commit do
AppointmentCreatedJob.perform_later(appointment)
end
appointment
end
end
# rest of the logic here ..
end
I have a monkey patching right now setup in my project, but I did not wanted to open a PR as the guidelines explicitly mention to avoid doing so without first discussing in the forum:
Rails.configuration.to_prepare do
require 'dry/operation/extensions/active_record'
class Dry::Operation::Extensions::ActiveRecord::Builder < Module
def included(klass)
default_connection = @connection
default_options = @options
define_method(:transaction) do |connection = default_connection, **opts, &steps|
intercepting_failure do
result = nil
# Mind the block argument next line
connection.transaction(**default_options.merge(opts)) do |tx|
intercepting_failure(->(failure) {
result = failure
raise ::ActiveRecord::Rollback
}) do
result = steps.(tx)
end
end
result
end
end
end
end
end
I am happy to jump in, and submit a PR with this small fix, and tests to cover it, as well as updating the docs.