dry-rb / dry-transaction

Business transaction DSL
http://dry-rb.org/gems/dry-transaction
MIT License
468 stars 55 forks source link

Around step does not work correctly #150

Closed vitaliiorlov closed 9 months ago

vitaliiorlov commented 10 months ago

Describe the bug

Around step with ActiveRecord transaction does not work.

Getting this exception:

CreateOperation.new.call(test: 1)
/usr/local/bundle/gems/dry-transaction-0.15.0/lib/dry/transaction/step_adapters/around.rb:14:in `call': step +transaction+ must return a Result object (Dry::Transaction::InvalidResultError)

            raise InvalidResultError, options[:step_name]
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
irb(main):002>

To Reproduce

Operation:

# frozen_string_literal: true

class CreateOperation
  include Dry::Transaction(container: Container)

  around :transaction, with: "transaction"

  step :first
  step :last

  private

  def first(input)
    Success(input)
  end

  def last(input)
    Failure(input)
  end
end

Container:

# frozen_string_literal: true

class Container
  extend Dry::Container::Mixin
  extend Dry::Monads[:result]

  register "transaction" do |input, &block|
    result = nil

    begin
      ActiveRecord::Base.transaction do
        result = block.call(Success(input))

        raise ActiveRecord::Rollback if result.failure? # this raises here after `:last` step executed

        Success(input)
      end
    rescue ActiveRecord::Rollback => _e # this exception not catching
      # debugger not working here
      Failure(input)
    end
  end
end

Expected behavior

It works as expected. (https://dry-rb.org/gems/dry-transaction/0.15/around-steps/)

My environment

vitaliiorlov commented 9 months ago

It works with this code:

class Container
  extend Dry::Container::Mixin

  class Transaction
    include Dry::Monads[:result]

    def call(input, &block)
      result = nil

      ActiveRecord::Base.transaction do
        result = block.call(Success(input))

        raise ActiveRecord::Rollback if result.failure?
      end

      result
    end
  end

  register "transaction", Transaction.new
end

It would be great to update the documentation. Thank you for the awesome Dry-family gems 😃