Skip to content

Instantly share code, notes, and snippets.

@tylerhunt
Created September 25, 2024 11:00
Show Gist options
  • Save tylerhunt/4e4248ff350028fbce6dbb068dd588b1 to your computer and use it in GitHub Desktop.
Save tylerhunt/4e4248ff350028fbce6dbb068dd588b1 to your computer and use it in GitHub Desktop.
Monkey-patched `dry-operation` to fix failed transactions not returning failure (dry-rb/dry-operation#23)
require 'dry/operation'
require 'dry/operation/extensions/active_record'
module FixTransactionNotReturningFailure
def included(klass)
class_exec(@connection, @options) do |default_connection, options|
klass.define_method(
:transaction,
) do |connection = default_connection, **opts, &steps|
intercepted_success = nil
intercepted_failure = nil
connection.transaction(**options.merge(opts)) do
intercepting_failure(->(failure) {
intercepted_failure = failure
raise ::ActiveRecord::Rollback
}) do
intercepted_success = steps.call
end
end
throw_failure intercepted_failure if intercepted_failure
intercepted_success
end
end
end
end
Dry::Operation::Extensions::ActiveRecord::Builder
.prepend FixTransactionNotReturningFailure
class Operation < Dry::Operation
module YieldFailureToHandlerOnIntercept
def intercepting_failure(handler, &)
output = catching_failure(&)
case output
when ::Dry::Monads::Result::Failure
handler.arity == 1 ? handler.call(output) : handler.call
throw_failure(output)
else
output
end
end
end
include Dry::Operation::Extensions::ActiveRecord
include YieldFailureToHandlerOnIntercept
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment