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 `require`d, 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
- E
- N
- W
- Rails START:includes
@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]].
return a list of new constants found since the last call to watch_namespaces
# File activesupport/lib/active_support/dependencies.rb, line 95 95: def new_constants 96: constants = [] 97: 98: # Grab the list of namespaces that we're looking for new constants under 99: @watching.last.each do |namespace| 100: # Retrieve the constants that were present under the namespace when watch_namespaces 101: # was originally called 102: original_constants = @stack[namespace].last 103: 104: mod = Inflector.constantize(namespace) if Dependencies.qualified_const_defined?(namespace) 105: next unless mod.is_a?(Module) 106: 107: # Get a list of the constants that were added 108: new_constants = mod.local_constant_names - original_constants 109: 110: # self[namespace] returns an Array of the constants that are being evaluated 111: # for that namespace. For instance, if parent.rb requires child.rb, the first 112: # element of self[Object] will be an Array of the constants that were present 113: # before parent.rb was required. The second element will be an Array of the 114: # constants that were present before child.rb was required. 115: @stack[namespace].each do |namespace_constants| 116: namespace_constants.concat(new_constants) 117: end 118: 119: # Normalize the list of new constants, and add them to the list we will return 120: new_constants.each do |suffix| 121: constants << ([namespace, suffix] - ["Object"]).join("::") 122: end 123: end 124: constants 125: ensure 126: # A call to new_constants is always called after a call to watch_namespaces 127: pop_modules(@watching.pop) 128: end
Add a set of modules to the watch stack, remembering the initial constants
# File activesupport/lib/active_support/dependencies.rb, line 131 131: def watch_namespaces(namespaces) 132: watching = [] 133: namespaces.map do |namespace| 134: module_name = Dependencies.to_constant_name(namespace) 135: original_constants = Dependencies.qualified_const_defined?(module_name) ? 136: Inflector.constantize(module_name).local_constant_names : [] 137: 138: watching << module_name 139: @stack[module_name] << original_constants 140: end 141: @watching << watching 142: end