Skip to content

Commit f49d7a0

Browse files
authored
Merge pull request rails#55376 from byroot/hwia_transform_keys_fix-2
Fix HashWithIndifferentAccess#transform_keys! to avoid collisions
2 parents 5afb306 + ee80783 commit f49d7a0

File tree

2 files changed

+26
-11
lines changed

2 files changed

+26
-11
lines changed

activesupport/lib/active_support/hash_with_indifferent_access.rb

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -354,21 +354,26 @@ def transform_values(&block)
354354
NOT_GIVEN = Object.new # :nodoc:
355355

356356
def transform_keys(hash = NOT_GIVEN, &block)
357-
return to_enum(:transform_keys) if NOT_GIVEN.equal?(hash) && !block_given?
358-
dup.tap { |h| h.transform_keys!(hash, &block) }
357+
if NOT_GIVEN.equal?(hash)
358+
if block_given?
359+
self.class.new(super(&block))
360+
else
361+
to_enum(:transform_keys)
362+
end
363+
else
364+
self.class.new(super)
365+
end
359366
end
360367

361368
def transform_keys!(hash = NOT_GIVEN, &block)
362-
return to_enum(:transform_keys!) if NOT_GIVEN.equal?(hash) && !block_given?
363-
364-
if hash.nil?
365-
super
366-
elsif NOT_GIVEN.equal?(hash)
367-
keys.each { |key| self[yield(key)] = delete(key) }
368-
elsif block_given?
369-
keys.each { |key| self[hash[key] || yield(key)] = delete(key) }
369+
if NOT_GIVEN.equal?(hash)
370+
if block_given?
371+
replace(transform_keys(&block))
372+
else
373+
return to_enum(:transform_keys!)
374+
end
370375
else
371-
keys.each { |key| self[hash[key] || key] = delete(key) }
376+
replace(transform_keys(hash, &block))
372377
end
373378

374379
self

activesupport/test/hash_with_indifferent_access_test.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,16 @@ def test_indifferent_transform_keys
473473
assert_equal(["A", "bbb"], hash.keys) # asserting that order of keys is unchanged
474474
assert_instance_of ActiveSupport::HashWithIndifferentAccess, hash
475475

476+
hash = ActiveSupport::HashWithIndifferentAccess.new(@integers).transform_keys { |k| k + 1 }
477+
478+
assert_equal([1, 2], hash.keys)
479+
480+
repeating_strings = { "a" => 1, "aa" => 2, "aaa" => 3 }
481+
482+
hash = ActiveSupport::HashWithIndifferentAccess.new(repeating_strings).transform_keys { |k| "#{k}a" }
483+
484+
assert_equal(%w[aa aaa aaaa], hash.keys)
485+
476486
assert_raise TypeError do
477487
hash.transform_keys(nil)
478488
end

0 commit comments

Comments
 (0)