From e690a92b4498f2b65998656c625919767854623d Mon Sep 17 00:00:00 2001 From: Robin Dupret Date: Fri, 24 Feb 2017 23:27:15 +0100 Subject: [PATCH 1/2] Soft-deprecate the top-level HashWithIndifferentAccess class Since using a `ActiveSupport::Deprecation::DeprecatedConstantProxy` would prevent people from inheriting this class and extending it from the `ActiveSupport::HashWithIndifferentAccess` one would break the ancestors chain, that's the best option we have here. --- .../active_record/attribute_methods/dirty.rb | 6 +++--- activesupport/CHANGELOG.md | 6 ++++++ .../hash_with_indifferent_access.rb | 2 ++ activesupport/test/core_ext/hash_ext_test.rb | 4 ++++ guides/source/upgrading_ruby_on_rails.md | 19 +++++++++++++++++++ 5 files changed, 34 insertions(+), 3 deletions(-) diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index 31c1e687dc..6aa414ba6b 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -50,7 +50,7 @@ module ActiveRecord super.tap do @previous_mutation_tracker = nil clear_mutation_trackers - @changed_attributes = HashWithIndifferentAccess.new + @changed_attributes = ActiveSupport::HashWithIndifferentAccess.new end end @@ -70,13 +70,13 @@ module ActiveRecord def changes_applied @previous_mutation_tracker = mutation_tracker - @changed_attributes = HashWithIndifferentAccess.new + @changed_attributes = ActiveSupport::HashWithIndifferentAccess.new clear_mutation_trackers end def clear_changes_information @previous_mutation_tracker = nil - @changed_attributes = HashWithIndifferentAccess.new + @changed_attributes = ActiveSupport::HashWithIndifferentAccess.new forget_attribute_assignments clear_mutation_trackers end diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 0f43b1256f..d43927967f 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,9 @@ +* Soft-deprecated the top-level `HashWithIndifferentAcces` constant. + `ActiveSupport::HashWithIndifferentAccess` should be used instead. + + *Robin Dupret* (#28157) + + ## Rails 5.1.0.beta1 (February 23, 2017) ## * Cache `ActiveSupport::TimeWithZone#to_datetime` before freezing. diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb index f9b269ad69..1927cddf34 100644 --- a/activesupport/lib/active_support/hash_with_indifferent_access.rb +++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb @@ -316,4 +316,6 @@ module ActiveSupport end end +# :stopdoc: + HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index a6e3e59433..efe211677e 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -8,6 +8,8 @@ require "active_support/core_ext/object/deep_dup" require "active_support/inflections" class HashExtTest < ActiveSupport::TestCase + HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess + class IndifferentHash < ActiveSupport::HashWithIndifferentAccess end @@ -1133,6 +1135,8 @@ class HashExtToParamTests < ActiveSupport::TestCase end class HashToXmlTest < ActiveSupport::TestCase + HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess + def setup @xml_options = { root: :person, skip_instruct: true, indent: 0 } end diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md index 8ba00a2b10..6005298127 100644 --- a/guides/source/upgrading_ruby_on_rails.md +++ b/guides/source/upgrading_ruby_on_rails.md @@ -65,6 +65,25 @@ Overwrite /myapp/config/application.rb? (enter "h" for help) [Ynaqdh] Don't forget to review the difference, to see if there were any unexpected changes. +Upgrading from Rails 5.0 to Rails 5.1 +------------------------------------- + +For more information on changes made to Rails 5.1 please see the [release notes](5_1_release_notes.html). + +### Top-level `HashWithIndifferentAccess` is soft-deprecated + +If your application uses the the top-level `HashWithIndifferentAccess` class, you +should slowly move your code to use the `ActiveSupport::HashWithIndifferentAccess` +one. + +It is only soft-deprecated, which means that your code will not break at the +moment and no deprecation warning will be displayed but this constant will be +removed in the future. + +Also, if you have pretty old YAML documents containg dumps of such objects, +you may need to load and dump them again to make sure that they reference +the right constant and that loading them won't break in the future. + Upgrading from Rails 4.2 to Rails 5.0 ------------------------------------- From ac57a3ee0e9d484f3d665f42933fcda864546349 Mon Sep 17 00:00:00 2001 From: Robin Dupret Date: Fri, 24 Feb 2017 23:34:59 +0100 Subject: [PATCH 2/2] Add few tests for the top level `HashWithIndifferentAccess` This ensures that if we try to hard-deprecate it again in the future, we won't break these behaviors. --- activesupport/test/core_ext/hash_ext_test.rb | 24 ++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index efe211677e..525ea08abd 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -1090,6 +1090,30 @@ class HashExtTest < ActiveSupport::TestCase assert_equal 1, hash[:a] assert_equal 3, hash[:b] end + + def test_inheriting_from_top_level_hash_with_indifferent_access_preserves_ancestors_chain + klass = Class.new(::HashWithIndifferentAccess) + assert_equal ActiveSupport::HashWithIndifferentAccess, klass.ancestors[1] + end + + def test_inheriting_from_hash_with_indifferent_access_properly_dumps_ivars + klass = Class.new(::HashWithIndifferentAccess) do + def initialize(*) + @foo = "bar" + super + end + end + + yaml_output = klass.new.to_yaml + + # `hash-with-ivars` was introduced in 2.0.9 (https://git.io/vyUQW) + if Gem::Version.new(Psych::VERSION) >= Gem::Version.new("2.0.9") + assert_includes yaml_output, "hash-with-ivars" + assert_includes yaml_output, "@foo: bar" + else + assert_includes yaml_output, "hash" + end + end end class IWriteMyOwnXML