1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

let remove_constant still delete Kernel#autoload constants [rounds #8213]

The method #remove_const does not load the file, so we
can still remove the constant.
This commit is contained in:
Xavier Noria 2012-11-15 11:06:35 +01:00
parent f732f9b7b8
commit a8c3ea90f1
3 changed files with 25 additions and 13 deletions

View file

@ -1,6 +1,6 @@
## Rails 4.0.0 (unreleased) ##
* Dependencies no longer trigger Kernel#autoload in remove_const [fixes #8213]. *Xavier Noria*
* Dependencies no longer trigger Kernel#autoload in remove_constant [fixes #8213]. *Xavier Noria*
* Simplify mocha integration and remove monkey-patches, bumping mocha to 0.13.0. *James Mead*

View file

@ -649,6 +649,8 @@ module ActiveSupport #:nodoc:
parent_name = constants.empty? ? 'Object' : constants.join('::')
if parent = safe_constantize(parent_name)
log "removing constant #{const}"
# In an autoloaded user.rb like this
#
# autoload :Foo, 'foo'
@ -656,20 +658,30 @@ module ActiveSupport #:nodoc:
# 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)
# 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.rb" ourselves. While #const_defined? and #const_get? do
# require the file, #autoload? and #remove_const don't.
#
# We are going to remove the constant nonetheless ---which exists as
# far as Ruby is concerned--- because if the user removes the macro
# call from a class or module that were not autoloaded, as in the
# example above with Object, accessing to that constant must err.
unless parent.autoload?(to_remove)
begin
constantized = parent.const_get(to_remove, false)
rescue NameError
log "the constant #{const} is not reachable anymore, skipping"
return
else
constantized.before_remove_const if constantized.respond_to?(:before_remove_const)
end
end
begin
log "removing constant #{const}"
constantized = parent.const_get(to_remove, false)
parent.instance_eval { remove_const to_remove }
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

View file

@ -933,9 +933,9 @@ class DependenciesTest < ActiveSupport::TestCase
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"
assert_nil ActiveSupport::Dependencies.remove_constant(constant), "Kernel#autoload has been triggered by remove_constant"
assert !defined?(ShouldNotBeAutoloaded)
end
def test_load_once_constants_should_not_be_unloaded