module Aha::AugmentedHash
Public: Provides functionality for dealing with nested hashes.
Nested keys are represented by an array where the first element represents the the key to access the sub hash and the rest represent keys for that hash.
These arrays can be nested allowing us to represent keys for an arbitrarily nested hash. This way of representing keys is used throughout Aha
and is heavily inspired by the Prismatic's Clojure fnk style destructuring as seen here: github.com/Prismatic/plumbing/tree/master/src/plumbing/fnk
For example:
Given the hash {a: 'hello', b: {c: 'augmented', d: {e: 'hash'}}} the keys :a, [:b, :c, [:d, :e]] would correspond to the values 'hello', 'augmented', 'hash'
Public Instance Methods
Public: Deletes a value within a nested hash. Equivalent to hash[..][kn-1].delete(kn)
hash - The nested hash to delete the value in. keys - They keys to the value to delete in order of depth.
Examples:
h = {:a => {'b' => {:c => 'hello', :d => 'world'}}} delete_in! h, :a, 'b', :c h # => {:a => {'b' => {:d => 'world'}}}
Returns nothing.
# File lib/aha/augmented_hash.rb, line 127 def delete_in!(hash, *keys) last_key = keys.pop get_in(hash, *keys).delete last_key end
Public: Removes the excluded keys from the hash.
hash - The hash to exclude keys from. keys - The keys to be excluded from the hash. Supports nested key syntax.
Examples:
h = {:a => {'b' => {:c => 'hello', :d => 'augmented'}}, :e => 'hash'} exclude! h, [:a, ['b', :d]], :e h # => {:a => {'b' => {:c => 'hello'}}}
Returns nothing.
# File lib/aha/augmented_hash.rb, line 145 def exclude!(hash, *keys) keys.each do |k| if k.is_a? Array subkey, *keys = k exclude!(hash[subkey], *keys) else hash.delete k end end end
Public: Retrieves a value from a nested hash. Equivalent to hash[..][kn]
hash - The hash to retrieve the value from. keys - The keys to the value in order of depth.
Examples:
h = {:a => {'b' => {:c => 'value'}}} get_in h, :a, 'b', :c # => 'value'
Returns the value if it exists and nil otherwise
# File lib/aha/augmented_hash.rb, line 70 def get_in(hash, *keys) keys.reduce(hash) { |acc, k| acc[k] } end
Public: Creates a new hash consisting only keys given and their corresponding values.
hash - The hash to base the result on. keys - The keys that the new hash will contain. Supports nested key
syntax.
Examples:
h = {:a => {'b' => {:c => 'hello', :d => 'augmented'}}, :e => 'hash'} only h, [:a, ['b', :d]] # => {:a => {'b' => {:d => 'augmented'}}}
Returns the new, smaller hash.
# File lib/aha/augmented_hash.rb, line 170 def only(hash, *keys) result = {} result.tap do |r| keys.each do |k| if k.is_a? Array subkey, *keys = k r[subkey] = only(hash[subkey], *keys) else r[k] = hash[k] end end end end
Public: Sets a value within a nested hash. Equivalent to hash[..][kn] = val
hash - The nested hash to set the value in. keys - The keys to the value to set in order of depth. val - The new value to set.
Examples:
h = {:a => {'b' => {:c => 'value'}}} put_in! h, :a, 'b', :c, 'new_value' h # => {:a => {'b' => {:c => 'new_value'}}}
Returns nothing.
# File lib/aha/augmented_hash.rb, line 89 def put_in!(hash, *keys, val) last_key = keys.pop get_in(hash, *keys)[last_key] = val end
Public: Updates a value within a nested hash.
hash - The nested hash to update the value in. keys - The keys to the current value in order of depth block - A required block that is given the current value and should return
the updated value to be set.
Examples:
h = {:a => {'b' => {:c => 33}}} update_in!(h, :a, 'b', :c) { |v| v + 9} h # => {:a => {'b' => {:c => 42}}}
Returns nothing.
# File lib/aha/augmented_hash.rb, line 109 def update_in!(hash, *keys) put_in!(hash, *keys, yield(get_in(hash, *keys))) if block_given? end
Public: Similar to Hash#values_at except that it supports nested key syntax and is primarily intented to be used for destructuring assignment.
hash - The nested hash to extract values from. keys - They keys corresponding to the values to be extracted. Supports
nested key syntax.
Examples:
h = {'a' => 3, :b => {:c => 2, 'd' => {:e => 1}}} value_1, value_2, value_3 = vals_at h, 'a', [:b, :c, ['d', :e]] value_1 # => 3 value_2 # => 2 value_3 # => 1
Returns an array of values corresponding to the given keys.
# File lib/aha/augmented_hash.rb, line 42 def vals_at(hash, *keys) result = Aha::Helper::extract_option(:acc, keys) || [] result.tap do |acc| keys.each do |k| if k.is_a? Array subkey, *keys = k vals_at(hash[subkey], *keys, {acc: acc}) else acc << hash[k] end end end end