lib/dry/schema/path.rb in dry-schema-0.6.0 vs lib/dry/schema/path.rb in dry-schema-1.0.0

- old
+ new

@@ -6,19 +6,21 @@ module Schema # Path represents a list of keys in a hash # # @api private class Path + include Comparable include Enumerable - # !@attribute [r] keys - # @return [Array<Symbol>] + # @return [Array<Symbol>] attr_reader :keys + alias_method :root, :first + # Coerce a spec into a path object # - # @param [Symbol, String, Hash, Array<Symbol>] spec + # @param [Path, Symbol, String, Hash, Array<Symbol>] spec # # @return [Path] # # @api private def self.[](spec) @@ -27,14 +29,14 @@ new(Array[*spec]) when String new(spec.split(DOT).map(&:to_sym)) when Hash new(keys_from_hash(spec)) - when self + when Path spec else - raise ArgumentError, '+spec+ must be either a Symbol, Array or Hash' + raise ArgumentError, '+spec+ must be either a Symbol, Array, Hash or a Path' end end # Extract a list of keys from a hash # @@ -60,15 +62,41 @@ keys.index(key) end # @api private def include?(other) - !find { |key| (idx = other.index(key)) && keys[idx].equal?(key) }.nil? + return false unless same_root?(other) + return false if index? && other.index? && !last.equal?(other.last) + self >= other end # @api private def <=>(other) - keys.count <=> other.count + raise ArgumentError, "Can't compare paths from different branches" unless same_root?(other) + + return 0 if keys.eql?(other.keys) + + res = + map { |key| (idx = other.index(key)) && keys[idx].equal?(key) } + .compact + .reject { |value| value.equal?(false) } + + res.size < count ? 1 : -1 + end + + # @api private + def last + keys.last + end + + # @api private + def same_root?(other) + root.equal?(other.root) + end + + # @api private + def index? + last.is_a?(Integer) end end end end