mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Hash#deep_*_keys(!) recurse into nested arrays.
Following methods now recursively transform nested arrays, too. * Hash#deep_transform_keys * Hash#deep_transform_keys! * Hash#deep_stringify_keys * Hash#deep_stringify_keys! * Hash#deep_symbolize_keys * Hash#deep_symbolize_keys!
This commit is contained in:
parent
b7f9de27f0
commit
ac0b1d835d
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*
|
||||
|
||||
* Override `Time.at` to support the passing of Time-like values when called with a single argument.
|
||||
|
||||
*Andrew White*
|
||||
|
|
|
@ -73,34 +73,26 @@ class Hash
|
|||
|
||||
# Return 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
|
||||
|
||||
# Return 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' } }
|
||||
#
|
||||
|
@ -112,14 +104,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
|
||||
|
||||
# Return 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' } }
|
||||
#
|
||||
|
@ -131,8 +123,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
|
||||
|
|
|
@ -36,6 +36,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
|
||||
|
@ -72,6 +76,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
|
||||
|
@ -97,6 +104,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
|
||||
|
@ -122,6 +132,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
|
||||
|
@ -147,6 +160,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
|
||||
|
@ -192,6 +208,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
|
||||
|
@ -217,6 +236,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