Skip to content

Instantly share code, notes, and snippets.

@cbartlett
Created March 12, 2014 15:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cbartlett/9509258 to your computer and use it in GitHub Desktop.
Save cbartlett/9509258 to your computer and use it in GitHub Desktop.
Hash
# lib/core_ext/hash.rb
module CoreExt
module Hash
def deep_fetch(*keys, &default)
keys.inject(self) do |hsh, key|
hsh.fetch(key, &(proc { |*args| return default.call(*args) } if default))
end
end
end
end
Hash.class_eval do
include CoreExt::Hash
end
# lib/hash_patches.rb
class Hash
def except_blank!
# Remove empty values
values.each{|h| h.except_blank! if h.is_a?(Hash)}
# Remove empty inside array
values.select{|v| v.is_a?(Array)}.flatten.each{|h| h.except_blank! if h.is_a?(Hash)}
# Booleans are allowed
delete_if { |k, v| v.blank? and not !!v == v }
self
end
def except_blank
self.dup.except_blank!
end
def widdle(*symbols)
result = self
symbols.each { |s| result = result[s] rescue nil }
result
end
def symbolize_all_keys!
symbolize_keys!
# Symbolize each hash in values
values.each{|h| h.symbolize_all_keys! if h.is_a?(Hash)}
# Symbolize each hash inside array
values.select{|v| v.is_a?(Array)}.flatten.each{|h| h.symbolize_all_keys! if h.is_a?(Hash)}
self
end
def symbolize_all_keys
self.dup.symbolize_all_keys!
end
def stringify_all_keys!
stringify_keys!
# Symbolize each hash in values
values.each{|h| h.stringify_all_keys! if h.is_a?(Hash)}
# Symbolize each hash inside array
values.select{|v| v.is_a?(Array)}.flatten.each{|h| h.stringify_all_keys! if h.is_a?(Hash)}
self
end
def stringify_all_keys
self.dup.stringify_all_keys!
end
end
# config/initializers/hash.rb
require 'core_ext/hash'
Hash.class_eval do
def delete_blank
delete_if do |k, v|
(v.respond_to?(:empty?) ? v.empty? : !v) or (v.instance_of?(Hash) || v.instance_of?(BSON::OrderedHash)) && v.delete_blank.empty?
end
end
def recursive_symbolize_keys!
symbolize_keys!
# symbolize each hash in .values
values.each{|h| h.recursive_symbolize_keys! if h.is_a?(Hash) }
# symbolize each hash inside an array in .values
values.select{|v| v.is_a?(Array) }.flatten.each{|h| h.recursive_symbolize_keys! if h.is_a?(Hash) }
self
end
def recursive_symbolize_keys
self.dup.recursive_symbolize_keys!
end
#
# Recursive version of Hash#merge!
#
# Adds the contents of +other_hash+ to +hsh+,
# merging entries in +hsh+ with duplicate keys with those from +other_hash+.
#
# Compared with Hash#merge!, this method supports nested hashes.
# When both +hsh+ and +other_hash+ contains an entry with the same key,
# it merges and returns the values from both arrays.
#
# h1 = {"a" => 100, "b" => 200, "c" => {"c1" => 12, "c2" => 14}}
# h2 = {"b" => 254, "c" => {"c1" => 16, "c3" => 94}}
# h1.rmerge!(h2) #=> {"a" => 100, "b" => 254, "c" => {"c1" => 16, "c2" => 14, "c3" => 94}}
#
# Simply using Hash#merge! would return
#
# h1.merge!(h2) #=> {"a" => 100, "b" = >254, "c" => {"c1" => 16, "c3" => 94}}
#
def rmerge!(other_hash)
merge!(other_hash) do |key, oldval, newval|
oldval.class == self.class ? oldval.rmerge!(newval) : newval
end
end
#
# Recursive version of Hash#merge
#
# Compared with Hash#merge!, this method supports nested hashes.
# When both +hsh+ and +other_hash+ contains an entry with the same key,
# it merges and returns the values from both arrays.
#
# Compared with Hash#merge, this method provides a different approch
# for merging nasted hashes.
# If the value of a given key is an Hash and both +other_hash+ abd +hsh
# includes the same key, the value is merged instead replaced with
# +other_hash+ value.
#
# h1 = {"a" => 100, "b" => 200, "c" => {"c1" => 12, "c2" => 14}}
# h2 = {"b" => 254, "c" => {"c1" => 16, "c3" => 94}}
# h1.rmerge(h2) #=> {"a" => 100, "b" => 254, "c" => {"c1" => 16, "c2" => 14, "c3" => 94}}
#
# Simply using Hash#merge would return
#
# h1.merge(h2) #=> {"a" => 100, "b" = >254, "c" => {"c1" => 16, "c3" => 94}}
#
def rmerge(other_hash)
r = {}
merge(other_hash) do |key, oldval, newval|
r[key] = oldval.class == self.class ? oldval.rmerge(newval) : newval
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment