lib/dry/schema/message/or/multi_path.rb in dry-schema-1.9.2 vs lib/dry/schema/message/or/multi_path.rb in dry-schema-1.9.3

- old
+ new

@@ -1,9 +1,7 @@ # frozen_string_literal: true -require "dry/core/equalizer" - require "dry/schema/message/or/abstract" require "dry/schema/path" module Dry module Schema @@ -12,26 +10,88 @@ # A message type used by OR operations with different paths # # @api public class MultiPath < Abstract # @api private - attr_reader :root + class MessageArray + # @api private + def initialize(messages) + @messages = messages.flatten + end + # @api private + def _paths + @messages.map(&:_path) + end + + # @api private + def to_or(root) + self.class.new(@messages.map { _1.to_or(root) }) + end + + # @api private + def to_h + MessageSet.new(@messages).to_h + end + end + # @api private - def initialize(...) - super - flat_left = left.flatten - flat_right = right.flatten - @root = [*flat_left, *flat_right].map(&:_path).reduce(:&) - @left = flat_left.map { _1.to_or(root) } - @right = flat_right.map { _1.to_or(root) } + def self.handler(message) + handlers.find { |k,| message.is_a?(k) }&.last end + # @api private + private_class_method def self.handlers + @handlers ||= { + self => -> { _1 }, + Array => -> { MessageArray.new(_1) } + }.freeze + end + # @api public def to_h - @to_h ||= Path[[*root, :or]].to_h( - [MessageSet.new(left).to_h, MessageSet.new(right).to_h] - ) + @to_h ||= Path[[*root, :or]].to_h(messages.map(&:to_h)) + end + + # @api private + def messages + @messages ||= _messages.flat_map { _1.to_or(root) } + end + + # @api private + def root + @root ||= _messages.flat_map(&:_paths).reduce(:&) + end + + # @api private + def path + root + end + + # @api private + def _paths + @paths ||= [Path[root]] + end + + # @api private + def to_or(root) + self.root == root ? messages : [self] + end + + private + + # @api private + def _messages + @_messages ||= [left, right].map do |message| + handler = self.class.handler(message) + + unless handler + raise ArgumentError, + "#{message.inspect} is of unknown type #{message.class.inspect}" + end + + handler.(message) + end end end end end end