Class: Hash

Inherits:
Object show all
Defined in:
lib/wukong/extensions/hash.rb,
lib/wukong/extensions/hash_keys.rb

Constant Summary collapse

DEEP_MERGER =

lambda for recursive merges

proc do |key,v1,v2|
  (v1.respond_to?(:merge) && v2.respond_to?(:merge)) ? v1.merge(v2.compact, &Hash::DEEP_MERGER) : (v2.nil? ? v1 : v2)
end

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.zip(keys, values, default = nil, &block) ⇒ Object

Create a hash from an array of keys and corresponding values.



36
37
38
39
40
# File 'lib/wukong/extensions/hash.rb', line 36

def self.zip(keys, values, default=nil, &block)
  hash = block_given? ? Hash.new(&block) : Hash.new(default)
  keys.zip(values){|key,val| hash[key]=val }
  hash
end

Instance Method Details

#compactObject

remove all key-value pairs where the value is nil



134
135
136
# File 'lib/wukong/extensions/hash.rb', line 134

def compact
  reject{|key,val| val.nil? }
end

#compact!Object

Replace the hash with its compacted self



140
141
142
# File 'lib/wukong/extensions/hash.rb', line 140

def compact!
  replace(compact)
end

#compact_blankObject

remove all key-value pairs where the value is blank



147
148
149
# File 'lib/wukong/extensions/hash.rb', line 147

def compact_blank
  reject{|key,val| val.blank? }
end

#compact_blank!Object

Replace the hash with its compact_blank’ed self



153
154
155
# File 'lib/wukong/extensions/hash.rb', line 153

def compact_blank!
  replace(compact_blank)
end

#deep_delete(*args) ⇒ Object

Treat hash as tree of hashes:

x = { 1 => :val, :subhash => { 1 => :val1, 2 => :val2 } }
x.deep_delete(:subhash, 1)
#=> :val
x
#=> { 1 => :val, :subhash => { 2 => :val2 } }


125
126
127
128
129
# File 'lib/wukong/extensions/hash.rb', line 125

def deep_delete *args
  last_key  = args.pop
  last_hsh  = args.empty? ? self : (deep_get(*args)||{})
  last_hsh.delete(last_key)
end

#deep_get(*args) ⇒ Object

Treat hash as tree of hashes:

x = { 1 => :val, :subhash => { 1 => :val1 } }
x.deep_get(:subhash, 1)
# => :val
x.deep_get(:subhash, 2)
# => nil
x.deep_get(:subhash, 2, 3)
# => nil
x.deep_get(:subhash, 2)
# => nil


107
108
109
110
111
112
113
# File 'lib/wukong/extensions/hash.rb', line 107

def deep_get *args
  last_key = args.pop
  # dig down to last subtree (building out if necessary)
  hsh = args.inject(self){|h, k| h[k] || {} }
  # get leaf value
  hsh[last_key]
end

#deep_merge(hsh2) ⇒ Object

Merge hashes recursively. Nothing special happens to array values

x = { :subhash => { 1 => :val_from_x, 222 => :only_in_x, 333 => :only_in_x }, :scalar => :scalar_from_x}
y = { :subhash => { 1 => :val_from_y, 999 => :only_in_y },                    :scalar => :scalar_from_y }
x.deep_merge y
=> {:subhash=>{1=>:val_from_y, 222=>:only_in_x, 333=>:only_in_x, 999=>:only_in_y}, :scalar=>:scalar_from_y}
y.deep_merge x
=> {:subhash=>{1=>:val_from_x, 222=>:only_in_x, 333=>:only_in_x, 999=>:only_in_y}, :scalar=>:scalar_from_x}

Nil values always lose.

x = {:subhash=>{:nil_in_x=>nil, 1=>:val1,}, :nil_in_x=>nil}
y = {:subhash=>{:nil_in_x=>5},              :nil_in_x=>5}
y.deep_merge x
=> {:subhash=>{1=>:val1, :nil_in_x=>5}, :nil_in_x=>5}
x.deep_merge y
=> {:subhash=>{1=>:val1, :nil_in_x=>5}, :nil_in_x=>5}


67
68
69
# File 'lib/wukong/extensions/hash.rb', line 67

def deep_merge hsh2
  merge hsh2, &Hash::DEEP_MERGER
end

#deep_merge!(hsh2) ⇒ Object



71
72
73
# File 'lib/wukong/extensions/hash.rb', line 71

def deep_merge! hsh2
  merge! hsh2, &Hash::DEEP_MERGER
end

#deep_set(*args) ⇒ Object

Treat hash as tree of hashes:

x = { 1 => :val, :subhash => { 1 => :val1 } }
x.deep_set(:subhash, :cat, :hat)
# => { 1 => :val, :subhash => { 1 => :val1,   :cat => :hat } }
x.deep_set(:subhash, 1, :newval)
# => { 1 => :val, :subhash => { 1 => :newval, :cat => :hat } }


85
86
87
88
89
90
91
92
# File 'lib/wukong/extensions/hash.rb', line 85

def deep_set *args
  val      = args.pop
  last_key = args.pop
  # dig down to last subtree (building out if necessary)
  hsh = args.empty? ? self : args.inject(self){|h, k| h[k] ||= {} }
  # set leaf value
  hsh[last_key] = val
end

#reverse_merge(other_hash) ⇒ Object

Stolen from ActiveSupport::CoreExtensions::Hash::ReverseMerge.



158
159
160
# File 'lib/wukong/extensions/hash.rb', line 158

def reverse_merge(other_hash)
  other_hash.merge(self)
end

#reverse_merge!(other_hash) ⇒ Object

Stolen from ActiveSupport::CoreExtensions::Hash::ReverseMerge.



163
164
165
# File 'lib/wukong/extensions/hash.rb', line 163

def reverse_merge!(other_hash)
  replace(reverse_merge(other_hash))
end

#slice(*keys) ⇒ Object

Slice a hash to include only the given keys. This is useful for limiting an options hash to valid keys before passing to a method:

def search(criteria = {})
  assert_valid_keys(:mass, :velocity, :time)
end

search(options.slice(:mass, :velocity, :time))

Returns a new hash with only the given keys.



17
18
19
20
# File 'lib/wukong/extensions/hash.rb', line 17

def slice(*keys)
  allowed = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys)
  reject{|key,| !allowed.include?(key) }
end

#slice!(*keys) ⇒ Object

Replace the hash with only the given keys.



24
25
26
# File 'lib/wukong/extensions/hash.rb', line 24

def slice!(*keys)
  replace(slice(*keys))
end

#symbolize_keysObject

Return a new hash with all keys converted to symbols.



4
5
6
7
8
9
# File 'lib/wukong/extensions/hash_keys.rb', line 4

def symbolize_keys
  inject({}) do |options, (key, value)|
    options[(key.to_sym rescue key) || key] = value
    options
  end
end

#symbolize_keys!Object

Destructively convert all keys to symbols.



12
13
14
# File 'lib/wukong/extensions/hash_keys.rb', line 12

def symbolize_keys!
  self.replace(self.symbolize_keys)
end