dry-rb / dry-transaction

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

Keyword parameters not passed to wrapped step #144

Closed TastyPi closed 1 year ago

TastyPi commented 1 year ago

Describe the bug

Keyword parameters are not passed through properly when wrapping step.

To Reproduce

#!/usr/bin/env ruby

require "dry/container"
require "dry/transaction"

Container = Dry::Container.new
Container.register(:foo) do |foo:|
  Dry::Monads::Result::Success.new(foo)
end

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

  step :bar, with: :foo

  def bar(bar:)
    super(foo: bar)
  end
end

puts Tr.new.call(bar: "baz")

Results in this error:

bug.rb:7:in `block in <main>': missing keyword: :foo (ArgumentError)
        from /.../gems/dry-transaction-0.15.0/lib/dry/transaction/instance_methods.rb:85:in `method_missing'
        from bug.rb:17:in `bar'
        from /.../gems/dry-transaction-0.15.0/lib/dry/transaction/callable.rb:35:in `call'
        from /.../gems/dry-transaction-0.15.0/lib/dry/transaction/callable.rb:35:in `call'
        from /.../gems/dry-transaction-0.15.0/lib/dry/transaction/step_adapters/around.rb:11:in `call'
        from /.../gems/dry-transaction-0.15.0/lib/dry/transaction/step_adapters/raw.rb:13:in `call'
        from /.../gems/dry-transaction-0.15.0/lib/dry/transaction/step_adapter.rb:43:in `call'
        from /.../gems/dry-transaction-0.15.0/lib/dry/transaction/step_adapter.rb:43:in `call'
        from /.../gems/dry-transaction-0.15.0/lib/dry/transaction/step.rb:57:in `block in call'
        from /.../gems/dry-transaction-0.15.0/lib/dry/transaction/step.rb:64:in `with_broadcast'
        from /.../gems/dry-transaction-0.15.0/lib/dry/transaction/step.rb:57:in `call'
        from /.../gems/dry-transaction-0.15.0/lib/dry/transaction/stack.rb:21:in `block (3 levels) in compile'
        from /.../gems/dry-monads-1.6.0/lib/dry/monads/right_biased.rb:52:in `bind'
        from /.../gems/dry-transaction-0.15.0/lib/dry/transaction/stack.rb:21:in `block (2 levels) in compile'
        from /.../gems/dry-transaction-0.15.0/lib/dry/transaction/stack.rb:14:in `call'
        from /.../gems/dry-transaction-0.15.0/lib/dry/transaction/instance_methods.rb:29:in `call'
        from bug.rb:21:in `<main>'

Expected behavior

Should print Success("baz")

My environment

TastyPi commented 1 year ago

Ah this is because I misunderstood how the library intends for inputs to be passed to steps.

For others who run into this, the first parameter passed to the step is its input. Only one argument is passed to steps, which is either the value passed to call or the value of a successful previous step. All extra arguments to a step are set using with_step_args.

So the correct way to do my example would be:

#!/usr/bin/env ruby

require "dry/container"
require "dry/transaction"

Container = Dry::Container.new
Container.register(:foo) do |input|
  Dry::Monads::Result::Success.new(input[:foo])
end

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

  step :bar, with: :foo

  def bar(input)
    super({foo: input[:bar]})
  end
end

puts Tr.new.call(bar: "baz")