Last active
September 25, 2018 14:58
-
-
Save adjam/6a34fdfc0493bb015be3b411a7b00a56 to your computer and use it in GitHub Desktop.
Declaratively rename and delete key/value pairs in a ruby hash
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# refinement for Hash class that allows declarative remapping functions | |
# | |
# #remap(mapping) | |
# and | |
# #remap!(mapping) | |
# methods. | |
# The `mapping` hash maps key names in the original hash to their | |
# names in the resulting hash, e.g. | |
# `{ foo: 'bar' }.remap({foo: :fu}) => `{ fu: 'bar' }` | |
# There are two special values that can be used in a mapping: | |
# `:__delete__` means that the key will be deleted, and | |
# if the value responds to `#call`, it will be invoked with two arguments: | |
# the key and value from the original hash, and it is expected to return | |
# an array of length 2, where the first element is the new key, and i | |
# the second # element is the new value. | |
# | |
# Example: | |
# | |
# convert = { foo: 'bar' | |
# bar: ->(k, v) { [k.upcase, "#{k}_{v}" } | |
# } | |
# | |
# { foo: :baz, | |
# bar: 'hey' }.remap(convert) | |
# | |
# => | |
# { baz: 'bar', BAR: "bar_hey" } | |
# | |
# The #remap and #remap! functions are identical except the latter | |
# modifies the original hash in-place. | |
# | |
# To use this within a class or module, put | |
# `using HashUtil` below the definition of your class or module. | |
module HashUtil | |
def self.rename_hash(h, names) | |
names.each do |k, v| | |
next unless h.key?(k) | |
if v == :__delete__ | |
h.delete(k) | |
else | |
if v.respond_to?(:call) | |
r = v.call(k, h.delete(k)) | |
h[r[0]] = r[1] | |
else | |
h[v] = h.delete(k) | |
end | |
end | |
end | |
h | |
end | |
refine Hash do | |
def remap(names) | |
copy = Marshal.load(Marshal.dump(self)) | |
HashUtil.rename_hash(copy, names) | |
end | |
def remap!(names) | |
HashUtil.rename_hash(self, names) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment