lib/dry/schema/message_set.rb in dry-schema-1.4.3 vs lib/dry/schema/message_set.rb in dry-schema-1.5.0
- old
+ new
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require 'dry/equalizer'
+require "dry/equalizer"
module Dry
module Schema
# A set of messages used to generate errors
#
@@ -16,16 +16,10 @@
# A list of compiled message objects
#
# @return [Array<Message>]
attr_reader :messages
- # An internal hash that is filled in with dumped messages
- # when a message set is coerced to a hash
- #
- # @return [Hash<Symbol=>[Array,Hash]>]
- attr_reader :placeholders
-
# Options hash
#
# @return [Hash]
attr_reader :options
@@ -36,11 +30,10 @@
# @api private
def initialize(messages, options = EMPTY_HASH)
@messages = messages
@options = options
- initialize_placeholders!
end
# Iterate over messages
#
# @example
@@ -110,46 +103,42 @@
private
# @api private
def messages_map(messages = self.messages)
- return EMPTY_HASH if empty?
+ combine_message_hashes(messages.map(&:to_h))
+ end
- messages.group_by(&:path).reduce(placeholders) do |hash, (path, msgs)|
- node = path.reduce(hash) { |a, e| a[e] }
-
- msgs.each do |msg|
- node << msg
+ # @api private
+ def combine_message_hashes(hashes)
+ hashes.reduce(EMPTY_HASH.dup) do |a, e|
+ a.merge(e) do |_, *values|
+ combine_message_values(values)
end
-
- node.map!(&:dump)
-
- hash
end
end
# @api private
- def paths
- @paths ||= messages.map(&:path).uniq
+ def combine_message_values(values)
+ hashes, other = partition_message_values(values)
+ combined = combine_message_hashes(hashes)
+ flattened = other.flatten
+
+ if flattened.empty?
+ combined
+ elsif combined.empty?
+ flattened
+ else
+ [flattened, combined]
+ end
end
# @api private
- def initialize_placeholders!
- return @placeholders = EMPTY_HASH if empty?
-
- @placeholders = paths.reduce(EMPTY_HASH.dup) do |hash, path|
- curr_idx = 0
- last_idx = path.size - 1
- node = hash
-
- while curr_idx <= last_idx
- key = path[curr_idx]
- node = (node[key] || node[key] = curr_idx < last_idx ? {} : [])
- curr_idx += 1
- end
-
- hash
- end
+ def partition_message_values(values)
+ values
+ .map { |value| value.is_a?(Array) ? value : [value] }
+ .reduce(EMPTY_ARRAY.dup, :+)
+ .partition { |value| value.is_a?(Hash) && !value[:text].is_a?(String) }
end
end
end
end