class ActiveSupport::Dependencies::WatchStack - activesupport-4.2.4 Documentation

# class ActiveSupport::Dependencies::WatchStack

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.

### Public Class Methods

new() click to toggle source

@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]].

    # File lib/active_support/dependencies.rb, line 90
    def initialize
      @watching = []
      @stack = Hash.new { |h,k| h[k] = [] }
    end

### Public Instance Methods

each(&block) click to toggle source

    # File lib/active_support/dependencies.rb, line 95
    def each(&block)
      @stack.each(&block)
    end

new_constants() click to toggle source

Returns a list of new constants found since the last call to `watch_namespaces`.

    # File lib/active_support/dependencies.rb, line 105
    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.local_constants - original_constants

        # self[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 self[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("::")
        end
      end
      constants
    ensure
      # A call to new_constants is always called after a call to watch_namespaces
      pop_modules(@watching.pop)
    end

watch_namespaces(namespaces) click to toggle source

Add a set of modules to the watch stack, remembering the initial constants.

    # File lib/active_support/dependencies.rb, line 142
    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).local_constants : []

        @stack[module_name] << original_constants
        module_name
      end
    end

watching?() click to toggle source

    # File lib/active_support/dependencies.rb, line 99
    def watching?
      !@watching.empty?
    end

### Private Instance Methods

pop_modules(modules) click to toggle source

    # File lib/active_support/dependencies.rb, line 154
    def pop_modules(modules)
      modules.each { |mod| @stack[mod].pop }
    end