lib/active_support/dependencies.rb in activesupport-3.0.0.beta3 vs lib/active_support/dependencies.rb in activesupport-3.0.0.beta4
- old
+ new
@@ -45,10 +45,13 @@
# An array of qualified constant names that have been loaded. Adding a name to
# this array will cause it to be unloaded the next time Dependencies are cleared.
mattr_accessor :autoloaded_constants
self.autoloaded_constants = []
+ mattr_accessor :references
+ self.references = {}
+
# An array of constant names that need to be unloaded on every request. Used
# to allow arbitrary constants to be marked for unloading.
mattr_accessor :explicitly_unloadable_constants
self.explicitly_unloadable_constants = []
@@ -64,11 +67,11 @@
def initialize
@mutex = Mutex.new
end
def self.locked(*methods)
- methods.each { |m| class_eval "def #{m}(*) lock { super } end" }
+ methods.each { |m| class_eval "def #{m}(*) lock { super } end", __FILE__, __LINE__ }
end
def get(key)
(val = assoc(key)) ? val[1] : []
end
@@ -474,13 +477,41 @@
# Remove the constants that have been autoloaded, and those that have been
# marked for unloading.
def remove_unloadable_constants!
autoloaded_constants.each { |const| remove_constant const }
autoloaded_constants.clear
+ Reference.clear!
explicitly_unloadable_constants.each { |const| remove_constant const }
end
+ class Reference
+ @@constants = Hash.new { |h, k| h[k] = Inflector.constantize(k) }
+
+ attr_reader :name
+
+ def initialize(name)
+ @name = name.to_s
+ @@constants[@name] = name if name.respond_to?(:name)
+ end
+
+ def get
+ @@constants[@name]
+ end
+
+ def self.clear!
+ @@constants.clear
+ end
+ end
+
+ def ref(name)
+ references[name] ||= Reference.new(name)
+ end
+
+ def constantize(name)
+ ref(name).get
+ end
+
# 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
@@ -570,9 +601,10 @@
to_remove = names.pop
parent = Inflector.constantize(names * '::')
log "removing constant #{const}"
parent.instance_eval { remove_const to_remove }
+
return true
end
protected
def log_call(*args)