lib/micro/cases/flow.rb
# frozen_string_literal: true
module Micro
module Cases
class Flow
IsAUseCaseWithDefaults = -> arg { arg.is_a?(Array) && Micro.case?(arg[0]) && arg[1].is_a?(Hash) }
IsAValidUseCase = -> use_case { Micro.case?(use_case) || IsAUseCaseWithDefaults[use_case] }
attr_reader :use_cases
def self.build(args)
use_cases = Utils.map_use_cases(args)
raise Error::InvalidUseCases if use_cases.none?(&IsAValidUseCase)
new(use_cases)
end
def initialize(use_cases)
@use_cases = use_cases.dup.freeze
@next_ones = use_cases.dup
@first = @next_ones.shift
end
def inspect
'#<(%s) use_cases=%s>' % [self.class, @use_cases]
end
def call!(input:, result:)
first_result = __call_use_case(@first, result, input)
return first_result if @next_ones.empty?
__call_next_use_cases(first_result)
end
def call(input = Kind::Empty::HASH)
result = call!(input: input, result: Case::Result.new)
return result unless block_given?
result_wrapper = ::Micro::Case::Result::Wrapper.new(result)
yield(result_wrapper)
result_wrapper.output
end
alias __call__ call
def to_proc
Proc.new { |arg| call(arg) }
end
def then(use_case = nil, &block)
can_yield_self = respond_to?(:yield_self)
if block
raise_invalid_invocation_of_the_then_method if use_case
raise NotImplementedError if !can_yield_self
yield_self(&block)
else
return yield_self if !use_case && can_yield_self
raise_invalid_invocation_of_the_then_method unless ::Micro.case_or_flow?(use_case)
self.call.then(use_case)
end
end
private
def raise_invalid_invocation_of_the_then_method
raise Case::Error::InvalidInvocationOfTheThenMethod.new("#{self.class.name}#")
end
def __call_use_case(use_case, result, input)
__build_use_case(use_case, result, input).__call__
end
def __call_next_use_cases(first_result)
@next_ones.reduce(first_result) do |result, use_case|
break result if result.failure?
__call_use_case(use_case, result, result.data)
end
end
def __build_use_case(use_case, result, input)
return use_case.__new__(result, input) unless use_case.is_a?(Array)
use_case[0].__new__(result, input.merge(use_case[1]))
end
end
end
end