lib/darthjee/core_ext/hash.rb
# frozen_string_literal: true
require 'darthjee/core_ext/hash/cameliazable'
require 'darthjee/core_ext/hash/changeable'
require 'darthjee/core_ext/hash/key_changeable'
require 'darthjee/core_ext/hash/transposeable'
require 'darthjee/core_ext/hash/transformable'
module Darthjee
module CoreExt
# @api public
module Hash
autoload :ChainFetcher, "#{PATH}/hash/chain_fetcher"
autoload :DeepHashConstructor, "#{PATH}/hash/deep_hash_constructor"
autoload :KeyChanger, "#{PATH}/hash/key_changer"
autoload :KeysSorter, "#{PATH}/hash/keys_sorter"
autoload :Squasher, "#{PATH}/hash/squasher"
autoload :ValueChanger, "#{PATH}/hash/value_changer"
include Hash::Cameliazable
include Hash::KeyChangeable
include Hash::Changeable
include Hash::Transposeable
include Hash::Transformable
########################################
# Fetching methods
#########################################
# Crawls through the hash fetching a key value from inside it
#
# this is the equivalent of chaining several calls to fetch method
#
# ```
# hash.chain_fetch(:key1, :key2)
# hash.fetch(:key1).fetch(:key2)
# ```
#
# @param [::Array<::Object>] keys List of keys to be fetched
# @param [::Proc] block block to be called in case of key not found
# @yield (key_not_found, keys_missing) The result of the yield
# will be the returned value instead of raising KeyError
#
# @return [::Object] value fetched
#
# @example
# hash = {
# a: {
# b: { c: 1, d: 2 }
# }
# }
#
# hash.chain_fetch(:a, :b, :c) # returns 1
# hash.chain_fetch(:a, :c, :d) # raises KeyError
# hash.chain_fetch(:a, :c, :d) { 10 } # returns 10
# hash.chain_fetch(:a, :c, :d) { |key, _| key } # returns :c
# hash.chain_fetch(:a, :c, :d) { |_, missing| missing } # returns [:d]
def chain_fetch(*keys, &block)
::Hash::ChainFetcher.new(self, *keys, &block).fetch
end
end
end
end
class Hash
include Darthjee::CoreExt::Hash
end