提交 ac0b1d83 编写于 作者: O OZAWA Sakuro

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!
上级 b7f9de27
* `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 @@ def assert_valid_keys(*valid_keys)
# 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 @@ def deep_stringify_keys
# 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 @@ def deep_symbolize_keys
# 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 @@ def setup
@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 @@ def test_deep_transform_keys
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 @@ def test_deep_transform_keys!
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 @@ def test_deep_symbolize_keys
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 @@ def test_deep_symbolize_keys!
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 @@ def test_deep_stringify_keys
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 @@ def test_deep_stringify_keys!
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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册