projects/command/src/concerns/domain_mappers.rb in foobara-0.0.37 vs projects/command/src/concerns/domain_mappers.rb in foobara-0.0.38
- old
+ new
@@ -1,36 +1,126 @@
module Foobara
class Command
module Concerns
module DomainMappers
+ class ForgotToDependOnDomainMapperError < Foobara::RuntimeError
+ context { mapper_name :string, :required }
+
+ attr_accessor :mapper
+
+ def initialize(mapper)
+ self.mapper = mapper
+ super()
+ end
+
+ def context
+ { mapper_name: mapper.name }
+ end
+
+ def message
+ "Did you maybe forget to add depends_on #{mapper.name}?"
+ end
+ end
+
+ class NoDomainMapperFoundError < Foobara::RuntimeError
+ context do
+ subcommand_name :string, :required
+ to :duck
+ end
+
+ attr_accessor :subcommand, :to
+
+ def initialize(subcommand, to)
+ self.subcommand = subcommand
+ self.to = to
+
+ super()
+ end
+
+ def context
+ { subcommand_name: subcommand.name, to: }
+ end
+
+ def message
+ "No DomainMapper found that maps to #{subcommand.name} or from its result"
+ end
+ end
+
include Concern
- def run_mapped_subcommand!(subcommand_class, *args)
- unmapped_inputs, has_result_type, result_type =
- case args.size
- when 1
- [args.first]
- when 2
- [args[1], true, args[0]]
- else
- # :nocov:
- raise ArgumentError,
- "Wrong number of arguments: (#{args.size}. Expected 2 or 3 argument."
- # :nocov:
- end
+ def run_mapped_subcommand!(subcommand_class, unmapped_inputs = {}, to = nil)
+ mapped_something = false
+ no_mapper_found = nil
- inputs = domain_map!(unmapped_inputs, to: subcommand_class, strict: true)
+ criteria = ->(mapper) { self.class.depends_on?(mapper) }
- result = run_subcommand!(subcommand_class, inputs)
+ inputs_mapper = self.class.domain.lookup_matching_domain_mapper(
+ from: unmapped_inputs,
+ to: subcommand_class,
+ criteria:,
+ strict: true
+ )
- if has_result_type
- result_mapper = self.class.domain.lookup_matching_domain_mapper!(
+ inputs = if inputs_mapper
+ mapped_something = true
+ run_subcommand!(inputs_mapper, from: unmapped_inputs)
+ else
+ unmapped_inputs
+ end
+
+ result_mapper = if subcommand_class.result_type
+ mapper = self.class.domain.lookup_matching_domain_mapper(
+ from: subcommand_class.result_type,
+ to:,
+ criteria:,
+ strict: true
+ )
+
+ no_mapper_found = mapper.nil? && inputs_mapper.nil?
+
+ mapper
+ end
+
+ result = unless no_mapper_found
+ run_subcommand!(subcommand_class, inputs)
+ end
+
+ unless subcommand_class.result_type
+ result_mapper = self.class.domain.lookup_matching_domain_mapper(
from: result,
- to: result_type,
+ to:,
+ criteria: ->(domain_mapper) { self.class.depends_on?(domain_mapper) },
strict: true
)
+ end
- result = result_mapper.map!(result)
+ if result_mapper
+ mapped_something = true
+ result = run_subcommand!(result_mapper, from: result)
+ end
+
+ unless mapped_something
+ mapper = self.class.domain.lookup_matching_domain_mapper(
+ from: unmapped_inputs,
+ to: subcommand_class,
+ strict: true
+ )
+
+ if mapper
+ raise ForgotToDependOnDomainMapperError, mapper
+ end
+
+ mapper = self.class.domain.lookup_matching_domain_mapper(
+ from: subcommand_class.result_type,
+ to:,
+ strict: true
+ )
+
+ if mapper
+ raise ForgotToDependOnDomainMapperError, mapper
+ end
+
+ raise NoDomainMapperFoundError.new(subcommand_class, to)
end
result
end