diff options
-rw-r--r-- | activesupport/CHANGELOG | 2 | ||||
-rw-r--r-- | activesupport/lib/active_support/dependencies.rb | 8 | ||||
-rw-r--r-- | activesupport/test/dependencies_test.rb | 11 |
3 files changed, 19 insertions, 2 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 84cdc22e40..383cdbb52f 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,6 +1,6 @@ *Rails 3.1.0 (unreleased)* -* No changes +* Added before_remove_const callback to ActiveSupport::Dependencies.remove_unloadable_constants! [Andrew White] *Rails 3.0.0 (August 29, 2010)* diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index e6170b2daf..4bd97d3ee3 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -511,7 +511,12 @@ module ActiveSupport #:nodoc: end # Remove the constants that have been autoloaded, and those that have been - # marked for unloading. + # marked for unloading. Before each constant is removed a callback is sent + # to its class/module if it implements +before_remove_const+. + # + # The callback implementation should be restricted to cleaning up caches, etc. + # as the enviroment will be in an inconsistent state, e.g. other constants + # may have already been unloaded and not accessible. def remove_unloadable_constants! autoloaded_constants.each { |const| remove_constant const } autoloaded_constants.clear @@ -636,6 +641,7 @@ module ActiveSupport #:nodoc: parent = Inflector.constantize(names * '::') log "removing constant #{const}" + constantize(const).before_remove_const if constantize(const).respond_to?(:before_remove_const) parent.instance_eval { remove_const to_remove } return true diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb index 77b885dc3d..bc7f597f1d 100644 --- a/activesupport/test/dependencies_test.rb +++ b/activesupport/test/dependencies_test.rb @@ -574,6 +574,17 @@ class DependenciesTest < Test::Unit::TestCase end end + def test_unloadable_constants_should_receive_callback + Object.const_set :C, Class.new + C.unloadable + C.expects(:before_remove_const).once + assert C.respond_to?(:before_remove_const) + ActiveSupport::Dependencies.clear + assert !defined?(C) + ensure + Object.class_eval { remove_const :C } if defined?(C) + end + def test_new_contants_in_without_constants assert_equal [], (ActiveSupport::Dependencies.new_constants_in(Object) { }) assert ActiveSupport::Dependencies.constant_watch_stack.all? {|k,v| v.empty? } |