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/lib | |
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/lib')
-rw-r--r-- | activesupport/lib/active_support/dependencies.rb | 44 |
1 files changed, 31 insertions, 13 deletions
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 |