Sha256: 8c1d916f31af92d3cb007b48ef84805d2d9ff45400763f44e16b6db30bd0de8a

Contents?: true

Size: 1.99 KB

Versions: 7

Compression:

Stored size: 1.99 KB

Contents

# frozen_string_literal: true

module Micro
  class Case
    module Flow
      class Reducer
        attr_reader :use_cases

        def self.map_use_cases(arg)
          return arg.use_cases if arg.is_a?(Reducer)
          return arg.__flow__.use_cases if arg.is_a?(Class) && arg < ::Micro::Case::Flow

          Array(arg)
        end

        def self.build(args)
          use_cases = Array(args).flat_map { |arg| map_use_cases(arg) }

          raise Error::InvalidUseCases if use_cases.any? { |klass| !(klass < ::Micro::Case) }

          new(use_cases)
        end

        def initialize(use_cases)
          @use_cases = use_cases
        end

        def call(arg = {})
          memo = arg.is_a?(Hash) ? arg.dup : {}

          @use_cases.reduce(initial_result(arg)) do |result, use_case|
            break result if result.failure?

            value = result.value
            input = value.is_a?(Hash) ? memo.tap { |data| data.merge!(value) } : value

            use_case_result(use_case, result, input)
          end
        end

        def >>(arg)
          self.class.build(use_cases + self.class.map_use_cases(arg))
        end

        def &(arg)
          raise NoMethodError, "undefined method `&' for #{self.inspect}. Please, use the method `>>' to avoid this error."
        end

        def to_proc
          Proc.new { |arg| call(arg) }
        end

        private

          def use_case_result(use_case, result, input)
            use_case.__new__(result, input).call
          end

          def initial_result(arg)
            return arg.call if arg_to_call?(arg)
            return arg if arg.is_a?(Micro::Case::Result)

            result = ::Micro::Case::Result.new
            result.__set__(true, arg, :ok, nil)
          end

          def arg_to_call?(arg)
            return true if arg.is_a?(::Micro::Case) || arg.is_a?(Reducer)
            return true if arg.is_a?(Class) && (arg < ::Micro::Case || arg < ::Micro::Case::Flow)
            return false
          end
      end
    end
  end
end

Version data entries

7 entries across 7 versions & 1 rubygems

Version Path
u-case-2.3.1 lib/micro/case/flow/reducer.rb
u-case-2.3.0 lib/micro/case/flow/reducer.rb
u-case-2.2.0 lib/micro/case/flow/reducer.rb
u-case-2.1.1 lib/micro/case/flow/reducer.rb
u-case-2.1.0 lib/micro/case/flow/reducer.rb
u-case-2.0.0 lib/micro/case/flow/reducer.rb
u-case-2.0.0.pre.4 lib/micro/case/flow/reducer.rb