From bff4d8d165486797227c5933e93a62e7f2c15d98 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Thu, 15 Nov 2012 04:33:17 +0100 Subject: dependencies no longer trigger Kernel#autoload in remove_const [fixes #8213] --- activesupport/lib/active_support/dependencies.rb | 44 +++++++++++++++++------- 1 file changed, 31 insertions(+), 13 deletions(-) (limited to 'activesupport/lib') 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 -- cgit v1.2.3