diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb index 1402c510e9fe8..2f771d7e97d2d 100644 --- a/activesupport/lib/active_support/hash_with_indifferent_access.rb +++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb @@ -378,13 +378,10 @@ def compact # Convert to a regular hash with string keys. def to_hash - _new_hash = Hash.new - set_defaults(_new_hash) - - each do |key, value| - _new_hash[key] = convert_value(value, conversion: :to_hash) - end - _new_hash + copy = Hash[self] + copy.transform_values! { |v| convert_value_to_hash(v) } + set_defaults(copy) + copy end def to_proc @@ -398,11 +395,7 @@ def convert_key(key) def convert_value(value, conversion: nil) if value.is_a? Hash - if conversion == :to_hash - value.to_hash - else - value.nested_under_indifferent_access - end + value.nested_under_indifferent_access elsif value.is_a?(Array) if conversion != :assignment || value.frozen? value = value.dup @@ -413,6 +406,17 @@ def convert_value(value, conversion: nil) end end + def convert_value_to_hash(value) + if value.is_a? Hash + value.to_hash + elsif value.is_a?(Array) + value.map { |e| convert_value_to_hash(e) } + else + value + end + end + + def set_defaults(target) if default_proc target.default_proc = default_proc.dup