dry-rb / dry-transaction

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

`try` step adapter may return nested `Right()` result #62

Closed giosakti closed 7 years ago

giosakti commented 7 years ago

Was it an expected behavior for try step adapter to wrap result with Right() ?

because when I try to do this:

try :persist!, catch: StandardError
...
def persist!(options)
  ### stuff ###
  Right(options)
end

I will get this result: Right(Right(...)) instead of the expected Right(...)

I see this code dry-transaction/lib/dry/transaction/step_adapters/try.rb was indeed wrap the result with Right()

def call(step, input, *args)
  unless step.options[:catch]
    raise ArgumentError, "+try+ steps require one or more exception classes provided via +catch:+"
  end

  Right(step.operation.call(input, *args))
rescue *Array(step.options[:catch]) => e
  e = step.options[:raise].new(e.message) if step.options[:raise]
  Left(e)
end
GustavoCaso commented 7 years ago

@giosakti in the example is a local step definition? or are you wrapping the step with the local method?

giosakti commented 7 years ago

for the example actually I want to do something like this

try :persist!, catch: StandardError
...
def persist!(options)
  if execute_something
    Right(options)
  else
    Left(options)
  end
end

the result will be something like this:

  1. in case of failure: Right(Left(...))
  2. in case of success: Right(Right(...))
GustavoCaso commented 7 years ago

The execute_something can not be in the operations object inside the container? Are you using a container?

I will play around with it but a quick solution for this case.

try :persist!, catch: StandardError
...
def persist!(options)
  if execute_something
    options # since it will be wrapped with Right anyway
  else
    {} #send something that will make operation fail
  end
end
giosakti commented 7 years ago

Ok, maybe I misunderstood the purpose of try step adapter

but I see different behavior when using normal step where you have to wrap the result explicitly with Either object, while you have to avoid wrapping with Either at all when using try

GustavoCaso commented 7 years ago

With step you have to make sure your operation or return Right or Left or Either but in other hand map will wrap your result with Right, tee will execute the code in the operation and will return Right with the initial input as for try if it succeed will return the result with Right if not with Left.

Hope this has help you understand it better. You can always go check the docs 😄

giosakti commented 7 years ago

ok thanks!