class Dry::Schema::Path

Path represents a list of keys in a hash

@api private

Attributes

keys[R]

@return [Array<Symbol>]

Public Class Methods

[](spec) click to toggle source

@api private

# File lib/dry/schema/path.rb, line 43
def self.[](spec)
  call(spec)
end
call(spec) click to toggle source

Coerce a spec into a path object

@param [Path, Symbol, String, Hash, Array<Symbol>] spec

@return [Path]

@api private

# File lib/dry/schema/path.rb, line 27
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"
  end
end
keys_from_hash(hash) click to toggle source

Extract a list of keys from a hash

@api private

# File lib/dry/schema/path.rb, line 50
def self.keys_from_hash(hash)
  hash.inject([]) { |a, (k, v)|
    v.is_a?(Hash) ? a.concat([k, *keys_from_hash(v)]) : a.concat([k, v])
  }
end
new(keys) click to toggle source

@api private

# File lib/dry/schema/path.rb, line 57
def initialize(keys)
  @keys = keys
end

Public Instance Methods

&(other) click to toggle source

@api private

# File lib/dry/schema/path.rb, line 126
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
<=>(other) click to toggle source

@api private

# File lib/dry/schema/path.rb, line 115
def <=>(other)
  raise ArgumentError, "Can't compare paths from different branches" unless same_root?(other)

  return 0 if keys.eql?(other.keys)

  res = key_matches(other).compact.reject { |value| value.equal?(false) }

  res.size < count ? 1 : -1
end
each(&block) click to toggle source

@api private

# File lib/dry/schema/path.rb, line 84
def each(&block)
  keys.each(&block)
end
include?(other) click to toggle source

@api private

# File lib/dry/schema/path.rb, line 98
def include?(other)
  if !same_root?(other)
    false
  elsif index?
    if other.index?
      last.equal?(other.last)
    else
      without_index.include?(other)
    end
  elsif other.index? && key_matches(other, :select).size < 2
    false
  else
    self >= other && !other.key_matches(self).include?(nil)
  end
end
index(key) click to toggle source

@api private

# File lib/dry/schema/path.rb, line 89
def index(key)
  keys.index(key)
end
index?() click to toggle source

@api private

# File lib/dry/schema/path.rb, line 152
def index?
  last.is_a?(Integer)
end
key_matches(other, meth = :map) click to toggle source

@api private

# File lib/dry/schema/path.rb, line 137
def key_matches(other, meth = :map)
  public_send(meth) { |key| (idx = other.index(key)) && keys[idx].equal?(key) }
end
last() click to toggle source

@api private

# File lib/dry/schema/path.rb, line 142
def last
  keys.last
end
same_root?(other) click to toggle source

@api private

# File lib/dry/schema/path.rb, line 147
def same_root?(other)
  root.equal?(other.root)
end
to_h(value = EMPTY_ARRAY.dup) click to toggle source

@api private

# File lib/dry/schema/path.rb, line 62
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
without_index() click to toggle source
# File lib/dry/schema/path.rb, line 93
def without_index
  self.class.new(to_a[0..-2])
end