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