The WatchStack
keeps a stack of the modules being watched as files are loaded. If a file in the process of being loaded (parent.rb) triggers the load of another file (child.rb) the stack will ensure that child.rb handles the new constants.
If child.rb is being autoloaded, its constants will be added to autoloaded_constants. If it was being required, they will be discarded.
This is handled by walking back up the watch stack and adding the constants found by child.rb to the list of original constants in parent.rb.
Methods
Included Modules
Attributes
[R] | watching | @watching is a stack of lists of constants being watched. For instance, if parent.rb is autoloaded, the stack will look like [[Object]]. If parent.rb then requires namespace/child.rb, the stack will look like [[Object], [Namespace]]. |
Class Public methods
new()
📝 Source code
# File activesupport/lib/active_support/dependencies.rb, line 102
def initialize
@watching = []
@stack = Hash.new { |h, k| h[k] = [] }
end
🔎 See on GitHub
Instance Public methods
each(&block)
📝 Source code
# File activesupport/lib/active_support/dependencies.rb, line 107
def each(&block)
@stack.each(&block)
end
🔎 See on GitHub
new_constants()
Returns a list of new constants found since the last call to watch_namespaces
.
📝 Source code
# File activesupport/lib/active_support/dependencies.rb, line 117
def new_constants
constants = []
# Grab the list of namespaces that we're looking for new constants under
@watching.last.each do |namespace|
# Retrieve the constants that were present under the namespace when watch_namespaces
# was originally called
original_constants = @stack[namespace].last
mod = Inflector.constantize(namespace) if Dependencies.qualified_const_defined?(namespace)
next unless mod.is_a?(Module)
# Get a list of the constants that were added
new_constants = mod.constants(false) - original_constants
# @stack[namespace] returns an Array of the constants that are being evaluated
# for that namespace. For instance, if parent.rb requires child.rb, the first
# element of @stack[Object] will be an Array of the constants that were present
# before parent.rb was required. The second element will be an Array of the
# constants that were present before child.rb was required.
@stack[namespace].each do |namespace_constants|
namespace_constants.concat(new_constants)
end
# Normalize the list of new constants, and add them to the list we will return
new_constants.each do |suffix|
constants << ([namespace, suffix] - ["Object"]).join("::".freeze)
end
end
constants
ensure
# A call to new_constants is always called after a call to watch_namespaces
pop_modules(@watching.pop)
end
🔎 See on GitHub
watch_namespaces(namespaces)
Add a set of modules to the watch stack, remembering the initial constants.
📝 Source code
# File activesupport/lib/active_support/dependencies.rb, line 154
def watch_namespaces(namespaces)
@watching << namespaces.map do |namespace|
module_name = Dependencies.to_constant_name(namespace)
original_constants = Dependencies.qualified_const_defined?(module_name) ?
Inflector.constantize(module_name).constants(false) : []
@stack[module_name] << original_constants
module_name
end
end
🔎 See on GitHub
watching?()
📝 Source code
# File activesupport/lib/active_support/dependencies.rb, line 111
def watching?
!@watching.empty?
end
🔎 See on GitHub