These are chat archives for dry-rb/chat

3rd
Oct 2018
Pablo Crivella
@pablocrivella
Oct 03 2018 08:52
What would be the best/easiest to mock the result of a Dry::Transcation::Operation when it returns a block?
Operation.new.call(arg) do |result|
  result.success { ... }
  result.failure { ... }
end
Piotr Solnica
@solnic
Oct 03 2018 09:04
@pablocrivella are you using rspec?
Pablo Crivella
@pablocrivella
Oct 03 2018 09:04
Yes
Piotr Solnica
@solnic
Oct 03 2018 09:04
too bad your operation is not injected and you manually instantiate it
this makes mocking it harder
Pablo Crivella
@pablocrivella
Oct 03 2018 09:07
I will try the injected version ASAP then :)

Is it still possible to inject a operation, even if i’m using inside other operation:

i.e:

class CheckAccess
  include Dry::Transaction::Operation

  def call(user)
    return Success(user.licenses.first) if active_license_for?(user)

    check_purchase = CheckPurchase.new
    check_purchase.call(user.purchases.first) do |result|
      result.success do |purchase|
        Success(purchase)
      end

      result.failure do
        if user.on_trial?
          Success(Trial.new(user: user))
        else
          Failure(user)
        end
      end
    end
  end

  private

  def active_license_for?(user)
    user.licenses.first_or_initialize.active?
  end
end
Viet (Drake) Tran
@tiev
Oct 03 2018 10:34
I prefer not using that block syntax at all. It’s a kind of dry-matcher Class enhancement.
I think it’s just a sugar-syntax that’s hard to write tests.
Just use normal Result matcher.
Or better, with the nature of your code, use Do notation
Tim Riley
@timriley
Oct 03 2018 10:38
In that context I personally would just use the plain Result API
check_purchase.call(user.purchases.first).or {
  if user.on_trial?
    Success(Trial.new(user: user))
  else
    Failure(user)
  end
}
Tim Riley
@timriley
Oct 03 2018 10:44
@pablocrivella also, that check_purchase operation cannot injected given you hard code its initialization in the call method
if you want it to be an injected dependency, you need to pass it to initialize
e.g.
def initialize(check_purchase:)
  @check_purchase = check_purchase
end
Then you can use it from inside #call and also inject a test double during your tests
Pablo Crivella
@pablocrivella
Oct 03 2018 10:57
Thanks @timriley ! I’ll take a look
Pablo Crivella
@pablocrivella
Oct 03 2018 12:56
There is not something similar to include Dry::Transaction(container: Container) for Operations right? Is that a flaw on my desing? should operations not depend on other operations as a common practice?