lib/dry/schema/path.rb in dry-schema-1.4.3 vs lib/dry/schema/path.rb in dry-schema-1.5.0

- old
+ new

@@ -1,15 +1,16 @@ # frozen_string_literal: true -require 'dry/schema/constants' +require "dry/schema/constants" module Dry module Schema # Path represents a list of keys in a hash # # @api private class Path + include Dry.Equalizer(:keys) include Comparable include Enumerable # @return [Array<Symbol>] attr_reader :keys @@ -21,25 +22,30 @@ # @param [Path, Symbol, String, Hash, Array<Symbol>] spec # # @return [Path] # # @api private - def self.[](spec) + def self.call(spec) case spec when Symbol, Array new(Array[*spec]) when String new(spec.split(DOT).map(&:to_sym)) when Hash new(keys_from_hash(spec)) when Path spec else - raise ArgumentError, '+spec+ must be either a Symbol, Array, Hash or a Path' + raise ArgumentError, "+spec+ must be either a Symbol, Array, Hash or a Path" end end + # @api private + def self.[](spec) + call(spec) + end + # Extract a list of keys from a hash # # @api private def self.keys_from_hash(hash) hash.inject([]) { |a, (k, v)| @@ -51,10 +57,32 @@ def initialize(keys) @keys = keys end # @api private + def to_h(value = EMPTY_ARRAY.dup) + curr_idx = 0 + last_idx = keys.size - 1 + hash = EMPTY_HASH.dup + node = hash + + while curr_idx <= last_idx + node = + node[keys[curr_idx]] = + if curr_idx == last_idx + value.is_a?(Array) ? value : [value] + else + EMPTY_HASH.dup + end + + curr_idx += 1 + end + + hash + end + + # @api private def each(&block) keys.each(&block) end # @api private @@ -81,11 +109,22 @@ res.size < count ? 1 : -1 end # @api private - def key_matches(other) - map { |key| (idx = other.index(key)) && keys[idx].equal?(key) } + def &(other) + unless same_root?(other) + raise ArgumentError, "#{other.inspect} doesn't have the same root #{inspect}" + end + + self.class.new( + key_matches(other, :select).compact.reject { |value| value.equal?(false) } + ) + end + + # @api private + def key_matches(other, meth = :map) + public_send(meth) { |key| (idx = other.index(key)) && keys[idx].equal?(key) } end # @api private def last keys.last