aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib
diff options
context:
space:
mode:
authorXavier Noria <fxn@hashref.com>2012-11-15 04:33:17 +0100
committerXavier Noria <fxn@hashref.com>2012-11-15 04:36:36 +0100
commitbff4d8d165486797227c5933e93a62e7f2c15d98 (patch)
treef71150c5ed14456cad67a6fb7b58430c7555e484 /activesupport/lib
parent77edb7cf55d4f0b487bd8e664f6d0725f362745d (diff)
downloadrails-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.rb44
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