Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 4728

Show
Ignore:
Timestamp:
08/08/06 21:21:04 (2 years ago)
Author:
ulysses
Message:

New dependencies implementation

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/actionmailer/CHANGELOG

    r4523 r4728  
    11*SVN* 
     2 
     3* Replace Reloadable with Reloadable::Deprecated. [Nicholas Seckar] 
    24 
    35* Mailer template root applies to a class and its subclasses rather than acting globally. #5555 [somekool@gmail.com] 
  • trunk/actionmailer/lib/action_mailer/base.rb

    r4526 r4728  
    188188    # Action Mailer subclasses should be reloaded by the dispatcher in Rails 
    189189    # when Dependencies.mechanism = :load. 
    190     include Reloadable::Subclasses 
     190    include Reloadable::Deprecated 
    191191     
    192192    private_class_method :new #:nodoc: 
  • trunk/actionpack/CHANGELOG

    r4717 r4728  
    11*SVN* 
    22 
     3<<<<<<< .mine 
     4* Replace Reloadable with Reloadable::Deprecated. [Nicholas Seckar] 
     5 
     6======= 
    37* Deprecation: check whether instance variables have been monkeyed with before assigning them to deprecation proxies. Raises a RuntimeError if so. [Jeremy Kemper] 
    48 
     
    711* Deprecation! @params, @session, @flash will be removed after 1.2. Use the corresponding instance methods instead. You'll get printed warnings during tests and logged warnings in dev mode when you access either instance variable directly. [Jeremy Kemper] 
    812 
     13>>>>>>> .r4727 
    914* Make Routing noisy when an anchor regexp is assigned to a segment. #5674 [francois.beausoleil@gmail.com] 
    1015 
  • trunk/actionpack/lib/action_controller/base.rb

    r4717 r4728  
    207207    DEFAULT_RENDER_STATUS_CODE = "200 OK" 
    208208     
    209     include Reloadable::Subclasses 
     209    include Reloadable::Deprecated 
    210210     
    211211    # Determines whether the view has access to controller internals @request, @response, @session, and @template. 
  • trunk/actionpack/lib/action_controller/caching.rb

    r4657 r4728  
    11require 'fileutils' 
     2require 'uri' 
    23 
    34module ActionController #:nodoc: 
     
    579580        # ActiveRecord::Observer will mark this class as reloadable even though it should not be. 
    580581        # However, subclasses of ActionController::Caching::Sweeper should be Reloadable 
    581         include Reloadable::Subclasses 
     582        include Reloadable::Deprecated 
    582583         
    583584        def before(controller) 
  • trunk/actionpack/lib/action_controller/layout.rb

    r4550 r4728  
    184184        def inherited_with_layout(child) 
    185185          inherited_without_layout(child) 
    186           child.send :include, Reloadable 
    187186          layout_match = child.name.underscore.sub(/_controller$/, '').sub(/^controllers\//, '') 
    188187          child.layout(layout_match) unless layout_list.grep(%r{layouts/#{layout_match}\.[a-z][0-9a-z]*$}).empty? 
  • trunk/actionpack/test/template/compiled_templates_test.rb

    r4546 r4728  
    11require 'test/unit' 
    22require File.dirname(__FILE__) + '/../../lib/action_view/helpers/date_helper' 
     3require File.dirname(__FILE__) + '/../../lib/action_view/compiled_templates' 
    34require File.dirname(__FILE__) + "/../abstract_unit" 
    45 
  • trunk/actionwebservice/CHANGELOG

    r4497 r4728  
    11*SVN* 
     2 
     3* Replace Reloadable with Reloadable::Deprecated. [Nicholas Seckar] 
    24 
    35* Fix invoke_layered since api_method didn't declare :expects. Closes #4720. [Kevin Ballard <kevin@sb.org>, Kent Sibilev] 
  • trunk/actionwebservice/lib/action_web_service/api.rb

    r3750 r4728  
    1717      # Action WebService API subclasses should be reloaded by the dispatcher in Rails 
    1818      # when Dependencies.mechanism = :load. 
    19       include Reloadable::Subclasses 
     19      include Reloadable::Deprecated 
    2020       
    2121      # Whether to transform the public API method names into camel-cased names  
  • trunk/actionwebservice/lib/action_web_service/base.rb

    r3750 r4728  
    3434    # Action WebService subclasses should be reloaded by the dispatcher in Rails 
    3535    # when Dependencies.mechanism = :load. 
    36     include Reloadable::Subclasses 
     36    include Reloadable::Deprecated 
    3737 
    3838    # Whether to report exceptions back to the caller in the protocol's exception 
  • trunk/actionwebservice/lib/action_web_service/struct.rb

    r4054 r4728  
    2222    # Action WebService Struct subclasses should be reloaded by the dispatcher in Rails 
    2323    # when Dependencies.mechanism = :load. 
    24     include Reloadable::Subclasses 
     24    include Reloadable::Deprecated 
    2525     
    2626    # If a Hash is given as argument to an ActionWebService::Struct constructor, 
  • trunk/activerecord/CHANGELOG

    r4721 r4728  
    11*SVN* 
    22 
     3<<<<<<< .mine 
     4* Replace Reloadable with Reloadable::Deprecated. [Nicholas Seckar] 
     5 
     6======= 
    37* Cache nil results for has_one associations so multiple calls don't call the database.  Closes #5757. [Michael A. Schoen] 
    48 
     
    711* Don't save has_one associations unnecessarily.  #5735 [Jonathan Viney] 
    812 
     13>>>>>>> .r4727 
    914* Refactor ActiveRecord::Base.reset_subclasses to #reset, and add global observer resetting.  [Rick Olson] 
    1015 
  • trunk/activerecord/lib/active_record/base.rb

    r4683 r4728  
    265265    cattr_accessor :logger 
    266266     
    267     include Reloadable::Subclasses 
     267    include Reloadable::Deprecated 
    268268     
    269269    def self.inherited(child) #:nodoc: 
     
    280280      nonreloadables = [] 
    281281      subclasses.each do |klass| 
    282         unless klass.reloadable? 
     282        unless Dependencies.autoloaded? klass 
    283283          nonreloadables << klass 
    284284          next 
  • trunk/activerecord/lib/active_record/observer.rb

    r4683 r4728  
    130130    # Observer subclasses should be reloaded by the dispatcher in Rails 
    131131    # when Dependencies.mechanism = :load. 
    132     include Reloadable::Subclasses 
     132    include Reloadable::Deprecated 
    133133 
    134134    class << self 
  • trunk/activesupport/CHANGELOG

    r4718 r4728  
    11*SVN* 
    22 
     3<<<<<<< .mine 
     4* Replace Reloadable with improvements to the Dependencies mechanism. [Nicholas Seckar] 
     5 
     6======= 
    37* DateTime#to_time gives hour/minute/second resolution.  #5747 [jon.evans@pobox.com] 
    48 
     
    913    attr_internal :foo 
    1014 
     15>>>>>>> .r4727 
    1116* Raise fully qualified names upon name errors. #5533 [lars@pinds.com, Nicholas Seckar] 
    1217 
  • trunk/activesupport/lib/active_support/dependencies.rb

    r4681 r4728  
    2323  self.mechanism = :load 
    2424 
     25  # The set of directories from which we may autoload files 
     26  mattr_accessor :autoload_paths 
     27  self.autoload_paths = [] 
     28 
     29  mattr_accessor :autoloaded_constants 
     30  self.autoloaded_constants = [] 
     31   
    2532  def load? 
    2633    mechanism == :load 
     
    2835 
    2936  def depend_on(file_name, swallow_load_errors = false) 
    30     require_or_load(file_name) 
     37    path = search_for_autoload_file(file_name) 
     38    require_or_load(path || file_name) 
    3139  rescue LoadError 
    3240    raise unless swallow_load_errors 
     
    3947  def clear 
    4048    loaded.clear 
    41   end 
    42  
    43   def require_or_load(file_name) 
     49    remove_autoloaded_constants! 
     50  end 
     51 
     52  def require_or_load(file_name, const_path = nil) 
    4453    file_name = $1 if file_name =~ /^(.*)\.rb$/ 
    4554    return if loaded.include?(file_name) 
     
    5362        # Enable warnings iff this file has not been loaded before and 
    5463        # warnings_on_first_load is set. 
     64        load_args = ["#{file_name}.rb"] 
     65        load_args << const_path unless const_path.nil? 
     66         
    5567        if !warnings_on_first_load or history.include?(file_name) 
    56           load "#{file_name}.rb" 
     68          load_file(*load_args) 
    5769        else 
    58           enable_warnings { load "#{file_name}.rb"
     70          enable_warnings { load_file(*load_args)
    5971        end 
    6072      rescue 
     
    7082  end 
    7183   
    72   # Return the a constant path for the provided parent and constant name 
    73   def constant_path_for(mod, name) 
    74     ([Object, Kernel].include? mod) ? name.to_s : "#{mod}::#{name}" 
     84  # Is the provided constant path defined? 
     85  def qualified_const_defined?(path) 
     86    raise NameError, "#{path.inspect} is not a valid constant name!" unless 
     87      /^(::)?([A-Z]\w*)(::[A-Z]\w*)*$/ =~ path 
     88    Object.module_eval("defined?(#{path})", __FILE__, __LINE__) 
     89  end 
     90   
     91  # Given +path+ return an array of constant paths which would cause Dependencies 
     92  # to attempt to load +path+. 
     93  def autoloadable_constants_for_path(path) 
     94    path = $1 if path =~ /\A(.*)\.rb\Z/ 
     95    expanded_path = File.expand_path(path) 
     96    autoload_paths.collect do |root| 
     97      expanded_root = File.expand_path root 
     98      next unless expanded_path.starts_with? expanded_root 
     99       
     100      nesting = expanded_path[(expanded_root.size)..-1] 
     101      nesting = nesting[1..-1] if nesting && nesting[0] == ?/ 
     102      next if nesting.blank? 
     103       
     104      nesting.camelize 
     105    end.compact.uniq 
     106  end 
     107   
     108  # Search for a file in the autoload_paths matching the provided suffix. 
     109  def search_for_autoload_file(path_suffix) 
     110    path_suffix = path_suffix + '.rb' unless path_suffix.ends_with? '.rb' 
     111    autoload_paths.each do |root| 
     112      path = File.join(root, path_suffix) 
     113      return path if File.file? path 
     114    end 
     115    nil # Gee, I sure wish we had first_match ;-) 
     116  end 
     117   
     118  # Does the provided path_suffix correspond to an autoloadable module? 
     119  def autoloadable_module?(path_suffix) 
     120    autoload_paths.any? do |autoload_path| 
     121      File.directory? File.join(autoload_path, path_suffix) 
     122    end 
     123  end 
     124   
     125  # Load the file at the provided path. +const_paths+ is a set of qualified 
     126  # constant names. When loading the file, Dependencies will watch for the 
     127  # addition of these constants. Each that is defined will be marked as 
     128  # autoloaded, and will be removed when Dependencies.clear is next called. 
     129  #  
     130  # If the second parameter is left off, then Dependencies will construct a set 
     131  # of names that the file at +path+ may define. See 
     132  # +autoloadable_constants_for_path+ for more details. 
     133  def load_file(path, const_paths = autoloadable_constants_for_path(path)) 
     134    const_paths = [const_paths].compact unless const_paths.is_a? Array 
     135    undefined_before = const_paths.reject(&method(:qualified_const_defined?)) 
     136     
     137    load path 
     138     
     139    autoloaded_constants.concat const_paths.select(&method(:qualified_const_defined?)) 
     140    autoloaded_constants.uniq! 
     141  end 
     142   
     143  # Return the constant path for the provided parent and constant name. 
     144  def qualified_name_for(mod, name) 
     145    mod_name = to_constant_name mod 
     146    (%w(Object Kernel).include? mod_name) ? name.to_s : "#{mod_name}::#{name}" 
     147  end 
     148   
     149  # Load the constant named +const_name+ which is missing from +from_mod+. If 
     150  # it is not possible to laod the constant into from_mod, try its parent module 
     151  # using const_missing. 
     152  def load_missing_constant(from_mod, const_name) 
     153    qualified_name = qualified_name_for from_mod, const_name 
     154    path_suffix = qualified_name.underscore 
     155    name_error = NameError.new("uninitialized constant #{qualified_name}") 
     156     
     157    file_path = search_for_autoload_file(path_suffix) 
     158    if file_path # We found a matching file to load 
     159      require_or_load file_path, qualified_name 
     160      raise LoadError, "Expected #{file_path} to define #{qualified_name}" unless from_mod.const_defined?(const_name) 
     161      return from_mod.const_get(const_name) 
     162    elsif autoloadable_module? path_suffix # Create modules for directories 
     163      mod = Module.new 
     164      from_mod.const_set const_name, mod 
     165      autoloaded_constants << qualified_name 
     166      return mod 
     167    elsif (parent = from_mod.parent) && parent != from_mod && 
     168          ! from_mod.parents.any? { |p| p.const_defined?(const_name) } 
     169      # If our parents do not have a constant named +const_name+ then we are free 
     170      # to attempt to load upwards. If they do have such a constant, then this 
     171      # const_missing must be due to from_mod::const_name, which should not 
     172      # return constants from from_mod's parents. 
     173      begin 
     174        return parent.const_missing(const_name) 
     175      rescue NameError => e 
     176        raise unless e.missing_name? qualified_name_for(parent, const_name) 
     177        raise name_error 
     178      end 
     179    else 
     180      raise name_error 
     181    end 
     182  end 
     183   
     184  # Remove the constants that have been autoloaded. 
     185  def remove_autoloaded_constants! 
     186    until autoloaded_constants.empty? 
     187      const = autoloaded_constants.shift 
     188      next unless qualified_const_defined? const 
     189      names = const.split('::') 
     190      if names.size == 1 || names.first.empty? # It's under Object 
     191        parent = Object 
     192      else 
     193        parent = (names[0..-2] * '::').constantize 
     194      end 
     195      parent.send :remove_const, names.last 
     196      true 
     197    end 
     198  end 
     199   
     200  # Determine if the given constant has been automatically loaded. 
     201  def autoloaded?(desc) 
     202    name = to_constant_name desc 
     203    return false unless qualified_const_defined? name 
     204    return autoloaded_constants.include?(name) 
    75205  end 
    76206   
     
    85215    end 
    86216  end 
     217 
     218protected 
     219   
     220  # Convert the provided const desc to a qualified constant name (as a string). 
     221  # A module, class, symbol, or string may be provided. 
     222  def to_constant_name(desc) 
     223    name = case desc 
     224      when String then desc.starts_with?('::') ? desc[2..-1] : desc 
     225      when Symbol then desc.to_s 
     226      when Module then desc.name 
     227      else raise TypeError, "Not a valid constant descriptor: #{desc.inspect}" 
     228    end 
     229  end 
     230   
    87231end 
    88232 
     
    98242  # require_association when using single-table inheritance. 
    99243  def const_missing(class_id) 
    100     file_name = class_id.to_s.demodulize.underscore 
    101     file_path = as_load_path.empty? ? file_name : "#{as_load_path}/#{file_name}" 
    102     begin 
    103       require_dependency(file_path) 
    104       brief_name = self == Object ? '' : "#{name}::" 
    105       raise NameError.new("uninitialized constant #{brief_name}#{class_id}") unless const_defined?(class_id) 
    106       return const_get(class_id) 
    107     rescue MissingSourceFile => e 
    108       # Re-raise the error if it does not concern the file we were trying to load. 
    109       raise unless e.is_missing? file_path 
    110        
    111       # Look for a directory in the load path that we ought to load. 
    112       if $LOAD_PATH.any? { |base| File.directory? "#{base}/#{file_path}" } 
    113         mod = Module.new 
    114         const_set class_id, mod # Create the new module 
    115         return mod 
    116       end 
    117        
    118       # Attempt to access the name from the parent, unless we don't have a valid 
    119       # parent, or the constant is already defined in the parent. If the latter 
    120       # is the case, then we are being queried via self::class_id, and we should 
    121       # avoid returning the constant from the parent if possible. 
    122       if parent && parent != self && ! parents.any? { |p| p.const_defined?(class_id) } 
    123         suppress(NameError) do 
    124           return parent.send(:const_missing, class_id) 
    125         end 
    126       end 
    127        
    128       qualified_name = Dependencies.constant_path_for self, class_id 
    129       raise NameError.new("uninitialized constant #{qualified_name}").copy_blame!(e) 
    130     end 
     244    Dependencies.load_missing_constant self, class_id 
    131245  end 
    132246end 
     
    141255      rescue NameError => e 
    142256        # Make sure that the name we are missing is the one that caused the error 
    143         parent_qualified_name = Dependencies.constant_path_for parent, class_id 
     257        parent_qualified_name = Dependencies.qualified_name_for parent, class_id 
    144258        raise unless e.missing_name? parent_qualified_name 
    145         qualified_name = Dependencies.constant_path_for self, class_id 
     259        qualified_name = Dependencies.qualified_name_for self, class_id 
    146260        raise NameError.new("uninitialized constant #{qualified_name}").copy_blame!(e) 
    147261      end 
  • trunk/activesupport/lib/active_support/deprecation.rb

    r4720 r4728  
    5050    module Assertions 
    5151      def assert_deprecated(match = nil, &block) 
    52         last = with_last_message_tracking_deprecation_behavior(&block) 
     52        last = collect_deprecations(&block).last 
    5353        assert last, "Expected a deprecation warning within the block but received none" 
    54         match = Regexp.new(Regexp.escape(match)) unless match.is_a?(Regexp) 
    55         assert_match match, last, "Deprecation warning didn't match #{match}: #{last}" 
     54        if match 
     55          match = Regexp.new(Regexp.escape(match)) unless match.is_a?(Regexp) 
     56          assert_match match, last, "Deprecation warning didn't match #{match}: #{last}" 
     57        end 
    5658      end 
    5759 
    5860      def assert_not_deprecated(&block) 
    59         last = with_last_message_tracking_deprecation_behavior(&block) 
    60         assert_nil last, "Expected no deprecation warning within the block but received one: #{last}" 
     61        deprecations = collect_deprecations(&block) 
     62        assert deprecations.empty?, "Expected no deprecation warning within the block but received #{deprecations.size}: \n  #{deprecations * "\n  "}" 
    6163      end 
    6264 
    6365      private 
    64         def with_last_message_tracking_deprecation_behavior 
     66         
     67        def collect_deprecations 
    6568          old_behavior = ActiveSupport::Deprecation.behavior 
    66           last_message = nil 
    67           ActiveSupport::Deprecation.behavior = Proc.new { |message| last_message = message; old_behavior.call(message) if old_behavior } 
     69          deprecations = [] 
     70          ActiveSupport::Deprecation.behavior = Proc.new do |message| 
     71            deprecations << message 
     72            old_behavior.call(message) if old_behavior 
     73          end 
    6874          yield 
    69           last_message 
     75          return deprecations 
    7076        ensure 
    7177          ActiveSupport::Deprecation.behavior = old_behavior 
  • trunk/activesupport/lib/active_support/reloadable.rb

    r3533 r4728  
    1 # Classes that include this module will automatically be reloaded 
    2 # by the Rails dispatcher when Dependencies.mechanism = :load. 
     1require 'active_support/deprecation' 
     2 
     3# A deprecated mechanism to mark a class reloadable. 
     4#  
     5# Deprecated as of Rails 1.2. 
     6# All autoloaded objects are now unloaded. 
    37module Reloadable 
    48  class << self 
     9     
    510    def included(base) #nodoc: 
     11      unless base.ancestors.include?(Reloadable::Subclasses) # Avoid double warning 
     12        ActiveSupport::Deprecation.warn "Reloadable has been deprecated and has no effect.", caller 
     13      end 
     14       
    615      raise TypeError, "Only Classes can be Reloadable!" unless base.is_a? Class 
    716       
    817      unless base.respond_to?(:reloadable?) 
    918        class << base 
    10           define_method(:reloadable?) { true } 
     19          define_method(:reloadable?) do 
     20            ActiveSupport::Deprecation.warn "Reloadable has been deprecated and reloadable? has no effect", caller 
     21            true 
     22          end 
    1123        end 
    1224      end 
     
    1628      included_in_classes.select { |klass| klass.reloadable? } 
    1729    end 
     30    # Commented out so dispatcher doesn't warn. Should we just disable Reloadable? 
     31    # deprecate :reloadable_classes 
    1832  end 
    1933   
    2034  # Captures the common pattern where a base class should not be reloaded, 
    2135  # but its subclasses should be. 
     36  #  
     37  # Deprecated as of Rails 1.2. 
     38  # All autoloaded objects are now unloaded. 
    2239  module Subclasses 
    2340    def self.included(base) #nodoc: 
    2441      base.send :include, Reloadable 
     42      ActiveSupport::Deprecation.warn "Reloadable::Subclasses has been deprecated and has no effect.", caller 
    2543      (class << base; self; end).send(:define_method, :reloadable?) do 
    26          base != self 
     44        ActiveSupport::Deprecation.warn "Reloadable has been deprecated and reloadable? has no effect", caller 
     45        base != self 
    2746      end 
    2847    end 
    2948  end 
     49   
     50  module Deprecated 
     51     
     52    def self.included(base) 
     53      class << base 
     54        define_method(:reloadable?) do 
     55          ActiveSupport::Deprecation.warn "Reloadable has been deprecated and reloadable? has no effect", caller 
     56          true # This might not have the desired effect, as AR::B.reloadable? => true. 
     57        end 
     58      end 
     59    end 
     60     
     61  end 
     62   
    3063end 
  • trunk/activesupport/test/caching_tools_test.rb

    r4595 r4728  
    11require File.dirname(__FILE__) + '/abstract_unit' 
     2require File.join(File.dirname(File.dirname(__FILE__)), 'lib/active_support/caching_tools.rb') 
    23 
    34class HashCachingTests < Test::Unit::TestCase 
  • trunk/activesupport/test/dependencies_test.rb

    r4681 r4728  
    11require File.dirname(__FILE__) + '/abstract_unit' 
    2 #require 'dependencies' 
    32 
    43class DependenciesTest < Test::Unit::TestCase 
     4   
    55  def teardown 
    66    Dependencies.clear 
    77  end 
    88 
    9   def with_loading(from_dir = nil) 
    10     prior_path = $LOAD_PATH.clone 
    11     $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/#{from_dir}" if from_dir 
     9  def with_loading(*from) 
    1210    old_mechanism, Dependencies.mechanism = Dependencies.mechanism, :load 
     11    dir = File.dirname(__FILE__) 
     12    prior_autoload_paths = Dependencies.autoload_paths 
     13    Dependencies.autoload_paths = from.collect { |f| "#{dir}/#{f}" } 
    1314    yield 
    1415  ensure 
    15     $LOAD_PATH.clear 
    16     $LOAD_PATH.concat prior_path 
     16    Dependencies.autoload_paths = prior_autoload_paths 
    1717    Dependencies.mechanism = old_mechanism 
    1818  end 
     
    160160    with_loading 'autoloading_fixtures' do 
    161161      begin 
    162         A::DoesNotExist 
     162        A::DoesNotExist.nil? 
    163163        flunk "No raise!!" 
    164164      rescue NameError => e 
     
    166166      end 
    167167      begin 
    168         A::B::DoesNotExist 
     168        A::B::DoesNotExist.nil? 
    169169        flunk "No raise!!" 
    170170      rescue NameError => e 
     
    183183  end 
    184184   
     185  def test_autoloadable_constants_for_path_should_handle_empty_autoloads 
     186    assert_equal [], Dependencies.autoloadable_constants_for_path('hello') 
     187  end 
     188   
     189  def test_autoloadable_constants_for_path_should_handle_relative_paths 
     190    fake_root = 'dependencies' 
     191    relative_root = File.dirname(__FILE__) + '/dependencies' 
     192    ['', '/'].each do |suffix| 
     193      with_loading fake_root + suffix do 
     194        assert_equal ["A::B"], Dependencies.autoloadable_constants_for_path(relative_root + '/a/b') 
     195      end 
     196    end 
     197  end 
     198   
     199  def test_autoloadable_constants_for_path_should_provide_all_results 
     200    fake_root = '/usr/apps/backpack' 
     201    with_loading fake_root, fake_root + '/lib' do 
     202      root = Dependencies.autoload_paths.first 
     203      assert_equal ["Lib::A::B", "A::B"], Dependencies.autoloadable_constants_for_path(root + '/lib/a/b') 
     204    end 
     205  end 
     206   
     207  def test_autoloadable_constants_for_path_should_uniq_results 
     208    fake_root = '/usr/apps/backpack/lib' 
     209    with_loading fake_root, fake_root + '/' do 
     210      root = Dependencies.autoload_paths.first 
     211      assert_equal ["A::B"], Dependencies.autoloadable_constants_for_path(root + '/a/b') 
     212    end 
     213  end 
     214   
     215  def test_qualified_const_defined 
     216    assert Dependencies.qualified_const_defined?("Object") 
     217    assert Dependencies.qualified_const_defined?("::Object") 
     218    assert Dependencies.qualified_const_defined?("::Object::Kernel") 
     219    assert Dependencies.qualified_const_defined?("::Object::Dependencies") 
     220    assert Dependencies.qualified_const_defined?("::Test::Unit::TestCase") 
     221  end 
     222   
     223  def test_autoloaded? 
     224    with_loading 'autoloading_fixtures' do 
     225      assert ! Dependencies.autoloaded?("ModuleFolder") 
     226      assert ! Dependencies.autoloaded?("ModuleFolder::NestedClass") 
     227       
     228      assert Dependencies.autoloaded?(ModuleFolder) 
     229       
     230      assert Dependencies.autoloaded?("ModuleFolder") 
     231      assert ! Dependencies.autoloaded?("ModuleFolder::NestedClass") 
     232       
     233      assert Dependencies.autoloaded?(ModuleFolder::NestedClass) 
     234       
     235      assert Dependencies.autoloaded?("ModuleFolder") 
     236      assert Dependencies.autoloaded?("ModuleFolder::NestedClass") 
     237       
     238      assert Dependencies.autoloaded?("::ModuleFolder") 
     239      assert Dependencies.autoloaded?(:ModuleFolder) 
     240       
     241      Object.send :remove_const, :ModuleFolder 
     242    end 
     243  end 
     244   
     245  def test_qualified_name_for 
     246    assert_equal "A", Dependencies.qualified_name_for(Object, :A) 
     247    assert_equal "A", Dependencies.qualified_name_for(:Object, :A) 
     248    assert_equal "A", Dependencies.qualified_name_for("Object", :A) 
     249    assert_equal "A", Dependencies.qualified_name_for("::Object", :A) 
     250    assert_equal "A", Dependencies.qualified_name_for("::Kernel", :A) 
     251     
     252    assert_equal "Dependencies::A", Dependencies.qualified_name_for(:Dependencies, :A) 
     253    assert_equal "Dependencies::A", Dependencies.qualified_name_for(Dependencies, :A) 
     254  end 
     255   
     256  def test_file_search 
     257    with_loading 'dependencies' do 
     258      root = Dependencies.autoload_paths.first 
     259      assert_equal nil, Dependencies.search_for_autoload_file('service_three') 
     260      assert_equal nil, Dependencies.search_for_autoload_file('service_three.rb') 
     261      assert_equal root + '/service_one.rb', Dependencies.search_for_autoload_file('service_one') 
     262      assert_equal root + '/service_one.rb', Dependencies.search_for_autoload_file('service_one.rb') 
     263    end 
     264  end 
     265   
     266  def test_file_search_uses_first_in_autoload_path 
     267    with_loading 'dependencies', 'autoloading_fixtures' do 
     268      deps, autoload = Dependencies.autoload_paths 
     269      assert_match %r/dependencies/, deps 
     270      assert_match %r/autoloading_fixtures/, autoload 
     271       
     272      assert_equal deps + '/conflict.rb', Dependencies.search_for_autoload_file('conflict') 
     273    end 
     274    with_loading 'autoloading_fixtures', 'dependencies' do 
     275      autoload, deps = Dependencies.autoload_paths 
     276      assert_match %r/dependencies/, deps 
     277      assert_match %r/autoloading_fixtures/, autoload 
     278       
     279      assert_equal autoload + '/conflict.rb', Dependencies.search_for_autoload_file('conflict') 
     280    end 
     281     
     282  end 
     283     
     284  def test_custom_const_missing_should_work 
     285    Object.module_eval <<-end_eval 
     286      module ModuleWithCustomConstMissing 
     287        def self.const_missing(name) 
     288          const_set name, name.to_s.hash 
     289        end 
     290 
     291        module A 
     292        end 
     293      end 
     294    end_eval 
     295     
     296    with_loading 'autoloading_fixtures' do 
     297      assert_kind_of Integer, ::ModuleWithCustomConstMissing::B 
     298      assert_kind_of Module, ::ModuleWithCustomConstMissing::A 
     299      assert_kind_of String, ::ModuleWithCustomConstMissing::A::B 
     300    end 
     301  end 
     302   
    185303end 
  • trunk/activesupport/test/deprecation_test.rb

    r4719 r4728  
    4040    end 
    4141  end 
    42  
     42   
    4343  def test_undeprecated 
    4444    assert_not_deprecated do 
     
    6868  def test_deprecated_instance_variable_proxy 
    6969    assert_not_deprecated { @dtc.request.size } 
    70  
     70     
    7171    assert_deprecated('@request.size') { assert_equal @dtc.request.size, @dtc.old_request.size } 
    7272    assert_deprecated('@request.to_s') { assert_equal @dtc.request.to_s, @dtc.old_request.to_s } 
    7373  end 
     74   
     75  def test_assert_deprecation_without_match 
     76    assert_deprecated do 
     77      @dtc.partially 
     78    end 
     79  end 
     80   
    7481end 
  • trunk/activesupport/test/reloadable_test.rb

    r4595 r4728  
    7979    end 
    8080  end 
     81   
     82  def test_including_reloadable_should_warn 
     83    c = Class.new 
     84    assert_deprecated %r{Reloadable} do 
     85      c.send :include, Reloadable 
     86    end 
     87     
     88    assert_deprecated { c.reloadable? } 
     89  end 
     90   
     91  def test_include_subclasses_should_warn 
     92    c = Class.new 
     93    deps = collect_deprecations do 
     94      c.send :include, Reloadable::Subclasses 
     95    end 
     96    assert_equal 1, deps.size 
     97    assert_match %r{Reloadable::Subclasses}, deps.first 
     98     
     99    assert_deprecated { c.reloadable? } 
     100  end 
     101   
     102  def test_include_deprecated_should_not_warn 
     103    c = Class.new 
     104    deps = collect_deprecations do 
     105      c.send :include, Reloadable::Deprecated 
     106    end 
     107    assert_equal 0, deps.size 
     108     
     109    assert c.respond_to?(:reloadable?) 
     110    assert_deprecated { c.reloadable? } 
     111  end 
     112   
    81113end 
  • trunk/railties/CHANGELOG

    r4716 r4728  
    11*SVN* 
    22 
     3<<<<<<< .mine 
     4* Add "require 'dispatcher'" to webrick server in the continuing quest to squash webrick weirdness. [Nicholas Seckar] 
     5 
     6* Add autoload_paths support to Initializer. [Nicholas Seckar] 
     7 
     8======= 
    39* Fix Dispatcher.reset_application! so that AR subclasses are removed and Observers re-initialized *after* Reloadable classes are removed. Closes #5743.  [Rick Olson] 
    410 
    511* Clarify usage of script/plugin source. Closes #5344. [james.adam@gmail.com] 
    612 
     13>>>>>>> .r4727 
    714* Add Dispatcher.to_prepare and config.to_prepare to provide a pre-request hook. [Nicholas Seckar] 
    815 
  • trunk/railties/lib/initializer.rb

    r4687 r4728  
    8181 
    8282      require_frameworks 
     83      set_autoload_paths 
    8384      load_environment 
    8485 
     
    124125      configuration.load_paths.reverse_each { |dir| $LOAD_PATH.unshift(dir) if File.directory?(dir) } 
    125126      $LOAD_PATH.uniq! 
     127    end 
     128     
     129    # Set the paths from which Rails will automatically load source files. 
     130    def set_autoload_paths 
     131      Dependencies.autoload_paths = configuration.autoload_paths.uniq 
     132      # Freeze the array so future modifications will fail rather than do nothing mysteriously 
     133      configuration.autoload_paths.freeze 
    126134    end 
    127135     
     
    413421    attr_accessor :load_paths 
    414422     
     423    # An array of paths from which Rails will automatically load classes and 
     424    # modules from. By default, all +app+, +lib+, +vendor+ and mock paths are 
     425    # included in this list. 
     426    attr_accessor :autoload_paths 
     427     
    415428    # The log level to use for the default Rails logger. In production mode, 
    416429    # this defaults to <tt>:info</tt>. In development mode, it defaults to 
     
    444457      self.frameworks                   = default_frameworks 
    445458      self.load_paths                   = default_load_paths 
     459      self.autoload_paths               = default_autoload_paths 
    446460      self.log_path                     = default_log_path 
    447461      self.log_level                    = default_log_level 
     
    547561        ).map { |dir| "#{framework_root_path}/#{dir}" }.select { |dir| File.directory?(dir) } 
    548562      end 
     563       
     564      def default_autoload_paths 
     565        paths = [] 
     566         
     567        # Add the app's controller directory 
     568        paths.concat(Dir["#{root_path}/app/controllers/"]) 
     569 
     570        # Then model subdirectories. 
     571        # TODO: Don't include .rb models as load paths 
     572        paths.concat(Dir["#{root_path}/app/models/[_a-z]*"]) 
     573        paths.concat(Dir["#{root_path}/components/[_a-z]*"]) 
     574 
     575        # Followed by the standard includes. 
     576        paths.concat %w( 
     577          app 
     578          app/models 
     579          app/controllers 
     580          app/helpers 
     581          app/services 
     582          app/apis 
     583          components 
     584          config 
     585          lib 
     586        ).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) } 
     587         
     588        paths.concat Dir["#{root_path}/vendor/plugins/*/lib/"] 
     589      end 
    549590 
    550591      def default_log_path 
  • trunk/railties/lib/webrick_server.rb

    r4688 r4728  
    44require 'cgi' 
    55require 'stringio' 
     6require 'dispatcher' 
    67 
    78include WEBrick