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