Sha256: 07cc89202ae4efa91a5f2d4110a79a8d87dccb0277ee078e4bc16d0bb4b51812

Contents?: true

Size: 1.72 KB

Versions: 8

Compression:

Stored size: 1.72 KB

Contents

module BusinessFlow
  # Isolate the logic around invoking a 'callable' -- a symbol representing a
  # method, a symbol representing another class which implements .call, or a
  # proc/lambda
  class Callable
    def initialize(callable, metaclass)
      @metaclass = metaclass
      @callable = callable
      check_callable
    end

    def call(instance, inputs)
      cached_proc.call(instance, inputs)
    end

    def to_s
      @callable.to_s
    end

    private

    # :reek:ManualDispatch Look reek I don't know what you want me to do.
    def check_callable
      if @callable.is_a?(Proc)
        @cached_proc = proc_callable
      elsif @callable.respond_to?(:call)
        @cached_proc = proc { |_, inputs| @callable.call(inputs) }
      elsif !@callable.is_a?(Symbol)
        raise ArgumentError, 'callable must be a symbol or respond to #call'
      end
    end

    def cached_proc
      @cached_proc ||=
        if @metaclass.method_defined?(@callable) ||
           @metaclass.private_method_defined?(@callable)
          proc { |instance, _| instance.send(@callable) }
        else
          @callable = lookup_callable ||
                      raise(NameError, "undefined constant #{@callable}")
          check_callable
        end
    end

    def proc_callable
      proc do |instance, inputs|
        if @callable.arity.zero?
          instance.instance_exec(&@callable)
        else
          instance.instance_exec(inputs, &@callable)
        end
      end
    end

    def lookup_callable
      constant_name = @callable.to_s.camelcase
      @metaclass.parents.each do |parent|
        begin
          return parent.const_get(constant_name)
        rescue NameError
          next
        end
      end
      nil
    end
  end
end

Version data entries

8 entries across 8 versions & 1 rubygems

Version Path
business_flow-0.5.2 lib/business_flow/callable.rb
business_flow-0.5.1 lib/business_flow/callable.rb
business_flow-0.5.0 lib/business_flow/callable.rb
business_flow-0.4.4 lib/business_flow/callable.rb
business_flow-0.4.3 lib/business_flow/callable.rb
business_flow-0.4.2 lib/business_flow/callable.rb
business_flow-0.4.1 lib/business_flow/callable.rb
business_flow-0.4.0 lib/business_flow/callable.rb