Module: Aha::AugmentedHash
Overview
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'
Instance Method Summary collapse
-
#delete_in!(hash, *keys) ⇒ Object
Public: Deletes a value within a nested hash.
-
#exclude!(hash, *keys) ⇒ Object
Public: Removes the excluded keys from the hash.
-
#get_in(hash, *keys) ⇒ Object
Public: Retrieves a value from a nested hash.
-
#only(hash, *keys) ⇒ Object
Public: Creates a new hash consisting only keys given and their corresponding values.
-
#put_in!(hash, *keys, val) ⇒ Object
Public: Sets a value within a nested hash.
-
#update_in!(hash, *keys) ⇒ Object
Public: Updates a value within a nested hash.
-
#vals_at(hash, *keys) ⇒ Object
Public: Similar to Hash#values_at except that it supports nested key syntax and is primarily intented to be used for destructuring assignment.
Instance Method Details
#delete_in!(hash, *keys) ⇒ Object
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.
127 128 129 130 |
# 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 |
#exclude!(hash, *keys) ⇒ Object
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.
145 146 147 148 149 150 151 152 153 154 |
# 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 |
#get_in(hash, *keys) ⇒ Object
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
70 71 72 |
# File 'lib/aha/augmented_hash.rb', line 70 def get_in(hash, *keys) keys.reduce(hash) { |acc, k| acc[k] } end |
#only(hash, *keys) ⇒ Object
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.
170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# 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 |
#put_in!(hash, *keys, val) ⇒ Object
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.
89 90 91 92 |
# 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 |
#update_in!(hash, *keys) ⇒ Object
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.
109 110 111 |
# 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 |
#vals_at(hash, *keys) ⇒ Object
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.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# 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 |