diff options
author | Xavier Noria <fxn@hashref.com> | 2012-11-15 04:33:17 +0100 |
---|---|---|
committer | Xavier Noria <fxn@hashref.com> | 2012-11-15 04:36:36 +0100 |
commit | bff4d8d165486797227c5933e93a62e7f2c15d98 (patch) | |
tree | f71150c5ed14456cad67a6fb7b58430c7555e484 /activesupport | |
parent | 77edb7cf55d4f0b487bd8e664f6d0725f362745d (diff) | |
download | rails-bff4d8d165486797227c5933e93a62e7f2c15d98.tar.gz rails-bff4d8d165486797227c5933e93a62e7f2c15d98.tar.bz2 rails-bff4d8d165486797227c5933e93a62e7f2c15d98.zip |
dependencies no longer trigger Kernel#autoload in remove_const [fixes #8213]
Diffstat (limited to 'activesupport')
-rw-r--r-- | activesupport/CHANGELOG.md | 2 | ||||
-rw-r--r-- | activesupport/lib/active_support/dependencies.rb | 44 | ||||
-rw-r--r-- | activesupport/test/autoloading_fixtures/should_not_be_required.rb | 1 | ||||
-rw-r--r-- | activesupport/test/dependencies_test.rb | 10 |
4 files changed, 44 insertions, 13 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 2bbc41296f..7daa0d5bca 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,5 +1,7 @@ ## Rails 4.0.0 (unreleased) ## +* Dependencies no longer trigger Kernel#autoload in remove_const [fixes #8213]. *Xavier Noria* + * Simplify mocha integration and remove monkey-patches, bumping mocha to 0.13.0. *James Mead* * `#as_json` isolates options when encoding a hash. diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index 42746582fa..00b1b3ec98 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -572,7 +572,6 @@ module ActiveSupport #:nodoc: # Determine if the given constant has been automatically loaded. def autoloaded?(desc) - # No name => anonymous module. return false if desc.is_a?(Module) && desc.anonymous? name = to_constant_name desc return false unless qualified_const_defined? name @@ -641,19 +640,38 @@ module ActiveSupport #:nodoc: end def remove_constant(const) #:nodoc: - return false unless qualified_const_defined? const + # Normalize ::Foo, ::Object::Foo, Object::Foo, Object::Object::Foo, etc. as Foo. + normalized = const.to_s.sub(/\A::/, '') + normalized.sub!(/\A(Object::)+/, '') + + constants = normalized.split('::') + to_remove = constants.pop + parent_name = constants.empty? ? 'Object' : constants.join('::') + + if parent = safe_constantize(parent_name) + # In an autoloaded user.rb like this + # + # autoload :Foo, 'foo' + # + # class User < ActiveRecord::Base + # end + # + # we correctly register "Foo" as being autoloaded. But if the app + # does not use the "Foo" constant we need to be careful not to + # trigger loading "foo". If the autoload has not been triggered + # we already know there is nothing to remove so just return. + return if parent.autoload?(to_remove) - # Normalize ::Foo, Foo, Object::Foo, and ::Object::Foo to Object::Foo - names = const.to_s.sub(/^::(Object)?/, 'Object::').split("::") - to_remove = names.pop - parent = Inflector.constantize(names * '::') - - log "removing constant #{const}" - constantized = constantize(const) - constantized.before_remove_const if constantized.respond_to?(:before_remove_const) - parent.instance_eval { remove_const to_remove } - - true + begin + log "removing constant #{const}" + constantized = parent.const_get(to_remove, false) + rescue NameError + log "the constant #{const} is not reachable anymore, skipping" + else + constantized.before_remove_const if constantized.respond_to?(:before_remove_const) + parent.instance_eval { remove_const to_remove } + end + end end protected diff --git a/activesupport/test/autoloading_fixtures/should_not_be_required.rb b/activesupport/test/autoloading_fixtures/should_not_be_required.rb new file mode 100644 index 0000000000..1fcf170cc5 --- /dev/null +++ b/activesupport/test/autoloading_fixtures/should_not_be_required.rb @@ -0,0 +1 @@ +ShouldNotBeAutoloaded = 0 diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb index 670a04e5df..6e5a6f71e2 100644 --- a/activesupport/test/dependencies_test.rb +++ b/activesupport/test/dependencies_test.rb @@ -928,6 +928,16 @@ class DependenciesTest < ActiveSupport::TestCase assert ! defined?(DeleteMe) end + def test_remove_constant_does_not_trigger_loading_autoloads + constant = 'ShouldNotBeAutoloaded' + Object.class_eval do + autoload constant, File.expand_path('../autoloading_fixtures/should_not_be_required', __FILE__) + end + ActiveSupport::Dependencies.remove_constant(constant) + + assert Object.autoload?(constant), "Kernel#autoload of #{constant} has been triggered by remove_const" + end + def test_load_once_constants_should_not_be_unloaded with_autoloading_fixtures do ActiveSupport::Dependencies.autoload_once_paths = ActiveSupport::Dependencies.autoload_paths |