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

Public Class Methods

included(base) click to toggle source

@api private

Calls superclass method
# File lib/dry/monads/do/all.rb, line 102
def included(base)
  super

  wrappers = ::Hash.new { _1[_2] = ::Module.new }
  tracker = MethodTracker.new(wrappers)
  base.extend(tracker)
  base.extend(InstanceMixin) unless base.is_a?(::Class)
  wrap_defined_methods(base, wrappers[base])
end
wrap_defined_methods(klass, target) click to toggle source

@api private

# File lib/dry/monads/do/all.rb, line 113
def wrap_defined_methods(klass, target)
  klass.public_instance_methods(false).each do |m|
    Do.wrap_method(target, m, :public)
  end

  klass.protected_instance_methods(false).each do |m|
    Do.wrap_method(target, m, :protected)
  end

  klass.private_instance_methods(false).each do |m|
    Do.wrap_method(target, m, :private)
  end
end