vendor/rails/activesupport/lib/active_support/dependencies.rb in radiant-0.7.2 vs vendor/rails/activesupport/lib/active_support/dependencies.rb in radiant-0.8.0
- old
+ new
@@ -1,10 +1,5 @@
-require 'set'
-require 'active_support/core_ext/module/attribute_accessors'
-require 'active_support/core_ext/load_error'
-require 'active_support/core_ext/kernel'
-
module ActiveSupport #:nodoc:
module Dependencies #:nodoc:
extend self
# Should we turn on Ruby warnings on the first load of dependent files?
@@ -42,18 +37,186 @@
# 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 = []
+ # The logger is used for generating information on the action run-time (including benchmarking) if available.
+ # Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers.
+ mattr_accessor :logger
+
# Set to true to enable logging of const_missing and file loads
mattr_accessor :log_activity
self.log_activity = false
# An internal stack used to record which constants are loaded by any block.
mattr_accessor :constant_watch_stack
self.constant_watch_stack = []
+ mattr_accessor :constant_watch_stack_mutex
+ self.constant_watch_stack_mutex = Mutex.new
+
+ # Module includes this module
+ module ModuleConstMissing #:nodoc:
+ def self.included(base) #:nodoc:
+ base.class_eval do
+ unless defined? const_missing_without_dependencies
+ alias_method_chain :const_missing, :dependencies
+ end
+ end
+ end
+
+ def self.excluded(base) #:nodoc:
+ base.class_eval do
+ if defined? const_missing_without_dependencies
+ undef_method :const_missing
+ alias_method :const_missing, :const_missing_without_dependencies
+ undef_method :const_missing_without_dependencies
+ end
+ end
+ end
+
+ # Use const_missing to autoload associations so we don't have to
+ # require_association when using single-table inheritance.
+ def const_missing_with_dependencies(class_id)
+ ActiveSupport::Dependencies.load_missing_constant self, class_id
+ end
+
+ def unloadable(const_desc = self)
+ super(const_desc)
+ end
+ end
+
+ # Class includes this module
+ module ClassConstMissing #:nodoc:
+ def const_missing(const_name)
+ if [Object, Kernel].include?(self) || parent == self
+ super
+ else
+ begin
+ begin
+ Dependencies.load_missing_constant self, const_name
+ rescue NameError
+ parent.send :const_missing, const_name
+ end
+ rescue NameError => e
+ # Make sure that the name we are missing is the one that caused the error
+ parent_qualified_name = Dependencies.qualified_name_for parent, const_name
+ raise unless e.missing_name? parent_qualified_name
+ qualified_name = Dependencies.qualified_name_for self, const_name
+ raise NameError.new("uninitialized constant #{qualified_name}").copy_blame!(e)
+ end
+ end
+ end
+ end
+
+ # Object includes this module
+ module Loadable #:nodoc:
+ def self.included(base) #:nodoc:
+ base.class_eval do
+ unless defined? load_without_new_constant_marking
+ alias_method_chain :load, :new_constant_marking
+ end
+ end
+ end
+
+ def self.excluded(base) #:nodoc:
+ base.class_eval do
+ if defined? load_without_new_constant_marking
+ undef_method :load
+ alias_method :load, :load_without_new_constant_marking
+ undef_method :load_without_new_constant_marking
+ end
+ end
+ end
+
+ def require_or_load(file_name)
+ Dependencies.require_or_load(file_name)
+ end
+
+ def require_dependency(file_name)
+ Dependencies.depend_on(file_name)
+ end
+
+ def require_association(file_name)
+ Dependencies.associate_with(file_name)
+ end
+
+ def load_with_new_constant_marking(file, *extras) #:nodoc:
+ if Dependencies.load?
+ Dependencies.new_constants_in(Object) { load_without_new_constant_marking(file, *extras) }
+ else
+ load_without_new_constant_marking(file, *extras)
+ end
+ rescue Exception => exception # errors from loading file
+ exception.blame_file! file
+ raise
+ end
+
+ def require(file, *extras) #:nodoc:
+ if Dependencies.load?
+ Dependencies.new_constants_in(Object) { super }
+ else
+ super
+ end
+ rescue Exception => exception # errors from required file
+ exception.blame_file! file
+ raise
+ end
+
+ # Mark the given constant as unloadable. Unloadable constants are removed each
+ # time dependencies are cleared.
+ #
+ # Note that marking a constant for unloading need only be done once. Setup
+ # or init scripts may list each unloadable constant that may need unloading;
+ # each constant will be removed for every subsequent clear, as opposed to for
+ # the first clear.
+ #
+ # The provided constant descriptor may be a (non-anonymous) module or class,
+ # or a qualified constant name as a string or symbol.
+ #
+ # Returns true if the constant was not previously marked for unloading, false
+ # otherwise.
+ def unloadable(const_desc)
+ Dependencies.mark_for_unload const_desc
+ end
+ end
+
+ # Exception file-blaming
+ module Blamable #:nodoc:
+ def blame_file!(file)
+ (@blamed_files ||= []).unshift file
+ end
+
+ def blamed_files
+ @blamed_files ||= []
+ end
+
+ def describe_blame
+ return nil if blamed_files.empty?
+ "This error occurred while loading the following files:\n #{blamed_files.join "\n "}"
+ end
+
+ def copy_blame!(exc)
+ @blamed_files = exc.blamed_files.clone
+ self
+ end
+ end
+
+ def hook!
+ Object.instance_eval { include Loadable }
+ Module.instance_eval { include ModuleConstMissing }
+ Class.instance_eval { include ClassConstMissing }
+ Exception.instance_eval { include Blamable }
+ true
+ end
+
+ def unhook!
+ ModuleConstMissing.excluded(Module)
+ Loadable.excluded(Object)
+ true
+ end
+
def load?
mechanism == :load
end
def depend_on(file_name, swallow_load_errors = false)
@@ -151,16 +314,17 @@
next unless %r{\A#{Regexp.escape(expanded_root)}(/|\\)} =~ expanded_path
nesting = expanded_path[(expanded_root.size)..-1]
nesting = nesting[1..-1] if nesting && nesting[0] == ?/
next if nesting.blank?
-
- [
- nesting.camelize,
- # Special case: application.rb might define ApplicationControlller.
- ('ApplicationController' if nesting == 'application')
- ]
+ nesting_camel = nesting.camelize
+ begin
+ qualified_const_defined?(nesting_camel)
+ rescue NameError
+ next
+ end
+ [ nesting_camel ]
end.flatten.compact.uniq
end
# Search for a file in load_paths matching the provided suffix.
def search_for_file(path_suffix)
@@ -337,20 +501,22 @@
# Handle the case where the module has yet to be defined.
initial_constants = if qualified_const_defined?(mod_name)
mod_name.constantize.local_constant_names
else
- []
+ []
end
else
raise Argument, "#{desc.inspect} does not describe a module!"
end
[mod_name, initial_constants]
end
- constant_watch_stack.concat watch_frames
+ constant_watch_stack_mutex.synchronize do
+ constant_watch_stack.concat watch_frames
+ end
aborting = true
begin
yield # Now yield to the code that is to define new constants.
aborting = false
@@ -363,12 +529,14 @@
mod = mod_name.constantize
next [] unless mod.is_a? Module
new_constants = mod.local_constant_names - prior_constants
# Make sure no other frames takes credit for these constants.
- constant_watch_stack.each do |frame_name, constants|
- constants.concat new_constants if frame_name == mod_name
+ constant_watch_stack_mutex.synchronize do
+ constant_watch_stack.each do |frame_name, constants|
+ constants.concat new_constants if frame_name == mod_name
+ end
end
new_constants.collect do |suffix|
mod_name == "Object" ? suffix : "#{mod_name}::#{suffix}"
end
@@ -385,24 +553,26 @@
return new_constants
ensure
# Remove the stack frames that we added.
if defined?(watch_frames) && ! watch_frames.blank?
- frame_ids = watch_frames.collect(&:object_id)
- constant_watch_stack.delete_if do |watch_frame|
- frame_ids.include? watch_frame.object_id
+ frame_ids = watch_frames.collect { |frame| frame.object_id }
+ constant_watch_stack_mutex.synchronize do
+ constant_watch_stack.delete_if do |watch_frame|
+ frame_ids.include? watch_frame.object_id
+ end
end
end
end
class LoadingModule #:nodoc:
# Old style environment.rb referenced this method directly. Please note, it doesn't
# actually *do* anything any more.
def self.root(*args)
- if defined?(RAILS_DEFAULT_LOGGER)
- RAILS_DEFAULT_LOGGER.warn "Your environment.rb uses the old syntax, it may not continue to work in future releases."
- RAILS_DEFAULT_LOGGER.warn "For upgrade instructions please see: http://manuals.rubyonrails.com/read/book/19"
+ if defined?(Rails) && Rails.logger
+ Rails.logger.warn "Your environment.rb uses the old syntax, it may not continue to work in future releases."
+ Rails.logger.warn "For upgrade instructions please see: http://manuals.rubyonrails.com/read/book/19"
end
end
end
# Convert the provided const desc to a qualified constant name (as a string).
@@ -434,120 +604,22 @@
return true
end
protected
def log_call(*args)
- if defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER && log_activity
- arg_str = args.collect(&:inspect) * ', '
+ if logger && log_activity
+ arg_str = args.collect { |arg| arg.inspect } * ', '
/in `([a-z_\?\!]+)'/ =~ caller(1).first
selector = $1 || '<unknown>'
log "called #{selector}(#{arg_str})"
end
end
def log(msg)
- if defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER && log_activity
- RAILS_DEFAULT_LOGGER.debug "Dependencies: #{msg}"
+ if logger && log_activity
+ logger.debug "Dependencies: #{msg}"
end
end
end
end
-Object.instance_eval do
- define_method(:require_or_load) { |file_name| ActiveSupport::Dependencies.require_or_load(file_name) } unless Object.respond_to?(:require_or_load)
- define_method(:require_dependency) { |file_name| ActiveSupport::Dependencies.depend_on(file_name) } unless Object.respond_to?(:require_dependency)
- define_method(:require_association) { |file_name| ActiveSupport::Dependencies.associate_with(file_name) } unless Object.respond_to?(:require_association)
-end
-
-class Module #:nodoc:
- # Rename the original handler so we can chain it to the new one
- alias :rails_original_const_missing :const_missing
-
- # Use const_missing to autoload associations so we don't have to
- # require_association when using single-table inheritance.
- def const_missing(class_id)
- ActiveSupport::Dependencies.load_missing_constant self, class_id
- end
-
- def unloadable(const_desc = self)
- super(const_desc)
- end
-
-end
-
-class Class
- def const_missing(const_name)
- if [Object, Kernel].include?(self) || parent == self
- super
- else
- begin
- begin
- ActiveSupport::Dependencies.load_missing_constant self, const_name
- rescue NameError
- parent.send :const_missing, const_name
- end
- rescue NameError => e
- # Make sure that the name we are missing is the one that caused the error
- parent_qualified_name = ActiveSupport::Dependencies.qualified_name_for parent, const_name
- raise unless e.missing_name? parent_qualified_name
- qualified_name = ActiveSupport::Dependencies.qualified_name_for self, const_name
- raise NameError.new("uninitialized constant #{qualified_name}").copy_blame!(e)
- end
- end
- end
-end
-
-class Object
- alias_method :load_without_new_constant_marking, :load
-
- def load(file, *extras) #:nodoc:
- ActiveSupport::Dependencies.new_constants_in(Object) { super }
- rescue Exception => exception # errors from loading file
- exception.blame_file! file
- raise
- end
-
- def require(file, *extras) #:nodoc:
- ActiveSupport::Dependencies.new_constants_in(Object) { super }
- rescue Exception => exception # errors from required file
- exception.blame_file! file
- raise
- end
-
- # Mark the given constant as unloadable. Unloadable constants are removed each
- # time dependencies are cleared.
- #
- # Note that marking a constant for unloading need only be done once. Setup
- # or init scripts may list each unloadable constant that may need unloading;
- # each constant will be removed for every subsequent clear, as opposed to for
- # the first clear.
- #
- # The provided constant descriptor may be a (non-anonymous) module or class,
- # or a qualified constant name as a string or symbol.
- #
- # Returns true if the constant was not previously marked for unloading, false
- # otherwise.
- def unloadable(const_desc)
- ActiveSupport::Dependencies.mark_for_unload const_desc
- end
-end
-
-# Add file-blaming to exceptions
-class Exception #:nodoc:
- def blame_file!(file)
- (@blamed_files ||= []).unshift file
- end
-
- def blamed_files
- @blamed_files ||= []
- end
-
- def describe_blame
- return nil if blamed_files.empty?
- "This error occurred while loading the following files:\n #{blamed_files.join "\n "}"
- end
-
- def copy_blame!(exc)
- @blamed_files = exc.blamed_files.clone
- self
- end
-end
+ActiveSupport::Dependencies.hook!