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