module Nuggets::Hash::DeepFetchMixin

Public Instance Methods

%(path, separator = '/')
Alias for: deep_fetch
deep_fetch(path[, separator]) → anObject click to toggle source
deep_fetch(path[, separator]) { |key| ... } → anObject

Recursively fetches keys in path, separated by separator if path is not an array, from hash. Maps each individual key according to the block if provided.

Examples:

hash = { 'foo' => { 'bar' => { 'baz' => 42 }, 'bay' => 23 } }
hash.deep_fetch('foo/bar/baz') #=> 42
hash.deep_fetch('foo/bar/bax') #=> nil
hash.deep_fetch('foo/bax/baz') #=> KeyError
hash.deep_fetch('foo/bay/baz') #=> TypeError
hash % 'foo/bar/baz' #=> 42
hash % %w[foo bar baz] #=> 42

hash = { foo: { bar: { baz: 42 } } }
hash.deep_fetch('foo/bar/baz', &:to_sym) #=> 42
hash % [:foo, :bar, :baz] #=> 42
# File lib/nuggets/hash/deep_fetch_mixin.rb, line 52
def deep_fetch(path, separator = '/')
  keys = path.is_a?(::Array) ? path : path.split(separator)
  raise ::ArgumentError, 'no keys given' if keys.empty?

  hash, klass = self, self.class

  loop {
    key = keys.shift
    key = yield key if block_given?

    return hash[key] if keys.empty?

    unless (hash = hash.fetch(key)).is_a?(klass)
      raise ::TypeError, '%p: %s expected, got %s' % [key, klass, hash.class]
    end
  }
end
Also aliased as: %