From b8dc06b8fdc16874160f61dcf58743fcc10e57db Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Fri, 8 Feb 2019 12:28:12 -0500 Subject: Add 'Hash#deep_transform_values', and 'Hash#deep_transform_values!' --- activesupport/lib/active_support/core_ext/hash.rb | 1 + .../core_ext/hash/deep_transform_values.rb | 52 ++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 activesupport/lib/active_support/core_ext/hash/deep_transform_values.rb (limited to 'activesupport/lib/active_support/core_ext') diff --git a/activesupport/lib/active_support/core_ext/hash.rb b/activesupport/lib/active_support/core_ext/hash.rb index c4b9e5f1a0..2f0901d853 100644 --- a/activesupport/lib/active_support/core_ext/hash.rb +++ b/activesupport/lib/active_support/core_ext/hash.rb @@ -2,6 +2,7 @@ require "active_support/core_ext/hash/conversions" require "active_support/core_ext/hash/deep_merge" +require "active_support/core_ext/hash/deep_transform_values" require "active_support/core_ext/hash/except" require "active_support/core_ext/hash/indifferent_access" require "active_support/core_ext/hash/keys" diff --git a/activesupport/lib/active_support/core_ext/hash/deep_transform_values.rb b/activesupport/lib/active_support/core_ext/hash/deep_transform_values.rb new file mode 100644 index 0000000000..ab68c34309 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/hash/deep_transform_values.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +class Hash + # Returns a new hash with all keys converted by the block operation. + # This includes the keys from the root hash and from all + # nested hashes and arrays. + # + # hash = { person: { name: 'Rob', age: '28' } } + # + # hash.deep_transform_values{ |value| value.to_s.upcase } + # # => {person: {name: "ROB", age: "28"}} + def deep_transform_values(&block) + _deep_transform_values_in_object(self, &block) + end + + # Destructively converts all values by using the block operation. + # This includes the values from the root hash and from all + # nested hashes and arrays. + def deep_transform_values!(&block) + _deep_transform_values_in_object!(self, &block) + end + + private + # support methods for deep transforming nested hashes and arrays + def _deep_transform_values_in_object(object, &block) + case object + when Hash + object.each_with_object({}) do |(key, value), result| + result[key] = _deep_transform_values_in_object(value, &block) + end + when Array + object.map { |e| _deep_transform_values_in_object(e, &block) } + else + yield(object) + end + end + + def _deep_transform_values_in_object!(object, &block) + case object + when Hash + object.keys.each do |key| + value = object.delete(key) + object[key] = _deep_transform_values_in_object!(value, &block) + end + object + when Array + object.map! { |e| _deep_transform_values_in_object!(e, &block) } + else + yield(object) + end + end +end -- cgit v1.2.3