mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #10887 from sakuro/deep_transform_keys_in_nested_arrays
Hash#deep_*_keys(!) recurse into nested arrays. Conflicts: activesupport/CHANGELOG.md
This commit is contained in:
commit
decd719711
3 changed files with 67 additions and 16 deletions
|
@ -1,3 +1,10 @@
|
|||
* `Hash#deep_transform_keys` and `Hash#deep_transform_keys!` now transform hashes
|
||||
in nested arrays. This change also applies to `Hash#deep_stringify_keys`,
|
||||
`Hash#deep_stringify_keys!`, `Hash#deep_symbolize_keys` and
|
||||
`Hash#deep_symbolize_keys!`.
|
||||
|
||||
*OZAWA Sakuro*
|
||||
|
||||
* Fixed confusing `DelegationError` in `Module#delegate`.
|
||||
|
||||
See #15186.
|
||||
|
|
|
@ -75,34 +75,26 @@ 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.
|
||||
# nested hashes and arrays.
|
||||
#
|
||||
# hash = { person: { name: 'Rob', age: '28' } }
|
||||
#
|
||||
# hash.deep_transform_keys{ |key| key.to_s.upcase }
|
||||
# # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
|
||||
def deep_transform_keys(&block)
|
||||
result = {}
|
||||
each do |key, value|
|
||||
result[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys(&block) : value
|
||||
end
|
||||
result
|
||||
_deep_transform_keys_in_object(self, &block)
|
||||
end
|
||||
|
||||
# Destructively convert all keys by using the block operation.
|
||||
# This includes the keys from the root hash and from all
|
||||
# nested hashes.
|
||||
# nested hashes and arrays.
|
||||
def deep_transform_keys!(&block)
|
||||
keys.each do |key|
|
||||
value = delete(key)
|
||||
self[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys!(&block) : value
|
||||
end
|
||||
self
|
||||
_deep_transform_keys_in_object!(self, &block)
|
||||
end
|
||||
|
||||
# Returns a new hash with all keys converted to strings.
|
||||
# This includes the keys from the root hash and from all
|
||||
# nested hashes.
|
||||
# nested hashes and arrays.
|
||||
#
|
||||
# hash = { person: { name: 'Rob', age: '28' } }
|
||||
#
|
||||
|
@ -114,14 +106,14 @@ class Hash
|
|||
|
||||
# Destructively convert all keys to strings.
|
||||
# This includes the keys from the root hash and from all
|
||||
# nested hashes.
|
||||
# nested hashes and arrays.
|
||||
def deep_stringify_keys!
|
||||
deep_transform_keys!{ |key| key.to_s }
|
||||
end
|
||||
|
||||
# Returns a new hash with all keys converted to symbols, as long as
|
||||
# they respond to +to_sym+. This includes the keys from the root hash
|
||||
# and from all nested hashes.
|
||||
# and from all nested hashes and arrays.
|
||||
#
|
||||
# hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
|
||||
#
|
||||
|
@ -133,8 +125,38 @@ class Hash
|
|||
|
||||
# Destructively convert all keys to symbols, as long as they respond
|
||||
# to +to_sym+. This includes the keys from the root hash and from all
|
||||
# nested hashes.
|
||||
# nested hashes and arrays.
|
||||
def deep_symbolize_keys!
|
||||
deep_transform_keys!{ |key| key.to_sym rescue key }
|
||||
end
|
||||
|
||||
private
|
||||
# support methods for deep transforming nested hashes and arrays
|
||||
def _deep_transform_keys_in_object(object, &block)
|
||||
case object
|
||||
when Hash
|
||||
object.each_with_object({}) do |(key, value), result|
|
||||
result[yield(key)] = _deep_transform_keys_in_object(value, &block)
|
||||
end
|
||||
when Array
|
||||
object.map {|e| _deep_transform_keys_in_object(e, &block) }
|
||||
else
|
||||
object
|
||||
end
|
||||
end
|
||||
|
||||
def _deep_transform_keys_in_object!(object, &block)
|
||||
case object
|
||||
when Hash
|
||||
object.keys.each do |key|
|
||||
value = object.delete(key)
|
||||
object[yield(key)] = _deep_transform_keys_in_object!(value, &block)
|
||||
end
|
||||
object
|
||||
when Array
|
||||
object.map! {|e| _deep_transform_keys_in_object!(e, &block)}
|
||||
else
|
||||
object
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -46,6 +46,10 @@ class HashExtTest < ActiveSupport::TestCase
|
|||
@nested_illegal_symbols = { [] => { [] => 3} }
|
||||
@upcase_strings = { 'A' => 1, 'B' => 2 }
|
||||
@nested_upcase_strings = { 'A' => { 'B' => { 'C' => 3 } } }
|
||||
@string_array_of_hashes = { 'a' => [ { 'b' => 2 }, { 'c' => 3 }, 4 ] }
|
||||
@symbol_array_of_hashes = { :a => [ { :b => 2 }, { :c => 3 }, 4 ] }
|
||||
@mixed_array_of_hashes = { :a => [ { :b => 2 }, { 'c' => 3 }, 4 ] }
|
||||
@upcase_array_of_hashes = { 'A' => [ { 'B' => 2 }, { 'C' => 3 }, 4 ] }
|
||||
end
|
||||
|
||||
def test_methods
|
||||
|
@ -84,6 +88,9 @@ class HashExtTest < ActiveSupport::TestCase
|
|||
assert_equal @nested_upcase_strings, @nested_symbols.deep_transform_keys{ |key| key.to_s.upcase }
|
||||
assert_equal @nested_upcase_strings, @nested_strings.deep_transform_keys{ |key| key.to_s.upcase }
|
||||
assert_equal @nested_upcase_strings, @nested_mixed.deep_transform_keys{ |key| key.to_s.upcase }
|
||||
assert_equal @upcase_array_of_hashes, @string_array_of_hashes.deep_transform_keys{ |key| key.to_s.upcase }
|
||||
assert_equal @upcase_array_of_hashes, @symbol_array_of_hashes.deep_transform_keys{ |key| key.to_s.upcase }
|
||||
assert_equal @upcase_array_of_hashes, @mixed_array_of_hashes.deep_transform_keys{ |key| key.to_s.upcase }
|
||||
end
|
||||
|
||||
def test_deep_transform_keys_not_mutates
|
||||
|
@ -109,6 +116,9 @@ class HashExtTest < ActiveSupport::TestCase
|
|||
assert_equal @nested_upcase_strings, @nested_symbols.deep_dup.deep_transform_keys!{ |key| key.to_s.upcase }
|
||||
assert_equal @nested_upcase_strings, @nested_strings.deep_dup.deep_transform_keys!{ |key| key.to_s.upcase }
|
||||
assert_equal @nested_upcase_strings, @nested_mixed.deep_dup.deep_transform_keys!{ |key| key.to_s.upcase }
|
||||
assert_equal @upcase_array_of_hashes, @string_array_of_hashes.deep_dup.deep_transform_keys!{ |key| key.to_s.upcase }
|
||||
assert_equal @upcase_array_of_hashes, @symbol_array_of_hashes.deep_dup.deep_transform_keys!{ |key| key.to_s.upcase }
|
||||
assert_equal @upcase_array_of_hashes, @mixed_array_of_hashes.deep_dup.deep_transform_keys!{ |key| key.to_s.upcase }
|
||||
end
|
||||
|
||||
def test_deep_transform_keys_with_bang_mutates
|
||||
|
@ -134,6 +144,9 @@ class HashExtTest < ActiveSupport::TestCase
|
|||
assert_equal @nested_symbols, @nested_symbols.deep_symbolize_keys
|
||||
assert_equal @nested_symbols, @nested_strings.deep_symbolize_keys
|
||||
assert_equal @nested_symbols, @nested_mixed.deep_symbolize_keys
|
||||
assert_equal @symbol_array_of_hashes, @string_array_of_hashes.deep_symbolize_keys
|
||||
assert_equal @symbol_array_of_hashes, @symbol_array_of_hashes.deep_symbolize_keys
|
||||
assert_equal @symbol_array_of_hashes, @mixed_array_of_hashes.deep_symbolize_keys
|
||||
end
|
||||
|
||||
def test_deep_symbolize_keys_not_mutates
|
||||
|
@ -159,6 +172,9 @@ class HashExtTest < ActiveSupport::TestCase
|
|||
assert_equal @nested_symbols, @nested_symbols.deep_dup.deep_symbolize_keys!
|
||||
assert_equal @nested_symbols, @nested_strings.deep_dup.deep_symbolize_keys!
|
||||
assert_equal @nested_symbols, @nested_mixed.deep_dup.deep_symbolize_keys!
|
||||
assert_equal @symbol_array_of_hashes, @string_array_of_hashes.deep_dup.deep_symbolize_keys!
|
||||
assert_equal @symbol_array_of_hashes, @symbol_array_of_hashes.deep_dup.deep_symbolize_keys!
|
||||
assert_equal @symbol_array_of_hashes, @mixed_array_of_hashes.deep_dup.deep_symbolize_keys!
|
||||
end
|
||||
|
||||
def test_deep_symbolize_keys_with_bang_mutates
|
||||
|
@ -204,6 +220,9 @@ class HashExtTest < ActiveSupport::TestCase
|
|||
assert_equal @nested_strings, @nested_symbols.deep_stringify_keys
|
||||
assert_equal @nested_strings, @nested_strings.deep_stringify_keys
|
||||
assert_equal @nested_strings, @nested_mixed.deep_stringify_keys
|
||||
assert_equal @string_array_of_hashes, @string_array_of_hashes.deep_stringify_keys
|
||||
assert_equal @string_array_of_hashes, @symbol_array_of_hashes.deep_stringify_keys
|
||||
assert_equal @string_array_of_hashes, @mixed_array_of_hashes.deep_stringify_keys
|
||||
end
|
||||
|
||||
def test_deep_stringify_keys_not_mutates
|
||||
|
@ -229,6 +248,9 @@ class HashExtTest < ActiveSupport::TestCase
|
|||
assert_equal @nested_strings, @nested_symbols.deep_dup.deep_stringify_keys!
|
||||
assert_equal @nested_strings, @nested_strings.deep_dup.deep_stringify_keys!
|
||||
assert_equal @nested_strings, @nested_mixed.deep_dup.deep_stringify_keys!
|
||||
assert_equal @string_array_of_hashes, @string_array_of_hashes.deep_dup.deep_stringify_keys!
|
||||
assert_equal @string_array_of_hashes, @symbol_array_of_hashes.deep_dup.deep_stringify_keys!
|
||||
assert_equal @string_array_of_hashes, @mixed_array_of_hashes.deep_dup.deep_stringify_keys!
|
||||
end
|
||||
|
||||
def test_deep_stringify_keys_with_bang_mutates
|
||||
|
|
Loading…
Reference in a new issue