module Dry::Monads::Do::All

Do::All automatically wraps methods defined in a class with an unwrapping block. Similar to what ‘Do.for(…)` does except wraps every method so you don’t have to list them explicitly.

@example annotated example

require 'dry/monads/do/all'
require 'dry/monads/result'

class CreateUser
  include Dry::Monads::Do::All
  include Dry::Monads::Result::Mixin

  def call(params)
    # Unwrap a monadic value using an implicitly passed block
    # if `validates` returns Failure, the execution will be halted
    values = yield validate(params)
    user = create_user(values)
    # If another block is passed to a method then takes
    # precedence over the unwrapping block
    safely_subscribe(values[:email]) { Logger.info("Already subscribed") }

    Success(user)
  end

  def validate(params)
    if params.key?(:email)
      Success(email: params[:email])
    else
      Failure(:no_email)
    end
  end

  def create_user(user)
    # Here a block is passed to the method but we don't use it
    UserRepo.new.add(user)
  end

  def safely_subscribe(email)
    repo = SubscriptionRepo.new

    if repo.subscribed?(email)
       # This calls the logger because a block
       # explicitly passed from `call`
       yield
    else
      repo.subscribe(email)
    end
  end
end