123456789_123456789_123456789_123456789_123456789_

Class: ActiveSupport::Dependencies::WatchStack

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Instance Chain:
self, ::Enumerable
Inherits: Object
Defined in: activesupport/lib/active_support/dependencies.rb

Overview

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.

Constant Summary

::Enumerable - Included

INDEX_WITH_DEFAULT

Class Method Summary

Instance Attribute Summary

::Enumerable - Included

#many?

Returns true if the enumerable has more than 1 element.

Instance Method Summary

::Enumerable - Included

#compact_blank

Returns a new ::Array without the blank items.

#exclude?

The negative of the Enumerable#include?.

#excluding

Returns a copy of the enumerable excluding the specified elements.

#including

Returns a new array that includes the passed elements.

#index_by

Convert an enumerable to a hash, using the block result as the key and the element as the value.

#index_with

Convert an enumerable to a hash, using the element as the key and the block result as the value.

#pick

Extract the given key from the first element in the enumerable.

#pluck

Extract the given key from each element in the enumerable.

#sum

Calculates a sum from the elements.

#without

Alias for #excluding.

Constructor Details

.newWatchStack

[ GitHub ]

  
# File 'activesupport/lib/active_support/dependencies.rb', line 115

def initialize
  @watching = []
  @stack = Hash.new { |h, k| h[k] = [] }
end

Instance Attribute Details

#watching (readonly)

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

[ GitHub ]

  
# File 'activesupport/lib/active_support/dependencies.rb', line 113

attr_reader :watching

#watching?Boolean (readonly)

[ GitHub ]

  
# File 'activesupport/lib/active_support/dependencies.rb', line 124

def watching?
  !@watching.empty?
end

Instance Method Details

#each(&block)

[ GitHub ]

  
# File 'activesupport/lib/active_support/dependencies.rb', line 120

def each(&block)
  @stack.each(&block)
end

#new_constants

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

[ GitHub ]

  
# File 'activesupport/lib/active_support/dependencies.rb', line 130

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("::")
    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)

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

[ GitHub ]

  
# File 'activesupport/lib/active_support/dependencies.rb', line 167

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