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

Changeset 4837

Show
Ignore:
Timestamp:
08/29/06 06:52:39 (2 years ago)
Author:
ulysses
Message:

Update Initializer to use load_once_paths to avoid plugin reloading. References #5852.
Add Dependencies.load_once_paths.

Files:

Legend:

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

    r4817 r4837  
    11*SVN* 
     2 
     3* Update Initializer to use load_once_paths to avoid plugin reloading. References #5852. [Nicholas Seckar] 
    24 
    35* Use Array#assoc in ActiveSupport::OrderedHash. [Mauricio Fernandez] 
  • trunk/activesupport/lib/active_support/dependencies.rb

    r4781 r4837  
    2222  mattr_accessor :mechanism 
    2323  self.mechanism = :load 
    24  
    25   # The set of directories from which we may autoload files 
    26   mattr_accessor :autoload_paths 
    27   self.autoload_paths = [] 
    28  
     24   
     25  # The set of directories from which we may automatically load files. Files 
     26  # under these directories will be reloaded on each request in development mode, 
     27  # unless the directory also appears in load_once_paths. 
     28  mattr_accessor :load_paths 
     29  self.load_paths = [] 
     30   
     31  # The set of directories from which automatically loaded constants are loaded 
     32  # only once. All directories in this set must also be present in +load_paths+. 
     33  mattr_accessor :load_once_paths 
     34  self.load_once_paths = [] 
     35   
    2936  # An array of qualified constant names that have been loaded. Adding a name to 
    3037  # this array will cause it to be unloaded the next time Dependencies are cleared. 
     
    4148 
    4249  def depend_on(file_name, swallow_load_errors = false) 
    43     path = search_for_autoload_file(file_name) 
     50    path = search_for_file(file_name) 
    4451    require_or_load(path || file_name) 
    4552  rescue LoadError 
     
    111118  end 
    112119   
    113   # Given +path+ return an array of constant paths which would cause Dependencies 
    114   # to attempt to load +path+. 
    115   def autoloadable_constants_for_path(path) 
     120  # Given +path+, a filesystem path to a ruby file, return an array of constant 
     121  # paths which would cause Dependencies to attempt to load this file. 
     122  #  
     123  def loadable_constants_for_path(path, bases = load_paths - load_once_paths) 
    116124    path = $1 if path =~ /\A(.*)\.rb\Z/ 
    117125    expanded_path = File.expand_path(path) 
    118     autoload_paths.collect do |root| 
     126    bases.collect do |root| 
    119127      expanded_root = File.expand_path root 
    120128      next unless expanded_path.starts_with? expanded_root 
     
    128136  end 
    129137   
    130   # Search for a file in the autoload_paths matching the provided suffix. 
    131   def search_for_autoload_file(path_suffix) 
     138  # Search for a file in load_paths matching the provided suffix. 
     139  def search_for_file(path_suffix) 
    132140    path_suffix = path_suffix + '.rb' unless path_suffix.ends_with? '.rb' 
    133     autoload_paths.each do |root| 
     141    load_paths.each do |root| 
    134142      path = File.join(root, path_suffix) 
    135143      return path if File.file? path 
     
    139147   
    140148  # Does the provided path_suffix correspond to an autoloadable module? 
     149  # Instead of returning a boolean, the autoload base for this module is returned.  
    141150  def autoloadable_module?(path_suffix) 
    142     autoload_paths.any? do |autoload_path| 
    143       File.directory? File.join(autoload_path, path_suffix) 
    144     end 
     151    load_paths.each do |load_path| 
     152      return load_path if File.directory? File.join(load_path, path_suffix) 
     153    end 
     154    nil 
     155  end 
     156   
     157  # Attempt to autoload the provided module name by searching for a directory 
     158  # matching the expect path suffix. If found, the module is created and assigned 
     159  # to +into+'s constants with the name +const_name+. Provided that the directory 
     160  # was loaded from a reloadable base path, it is added to the set of constants 
     161  # that are to be unloaded. 
     162  def autoload_module!(into, const_name, qualified_name, path_suffix) 
     163    return nil unless base_path = autoloadable_module?(path_suffix) 
     164    mod = Module.new 
     165    into.const_set const_name, mod 
     166    autoloaded_constants << qualified_name unless load_once_paths.include?(base_path) 
     167    return mod 
    145168  end 
    146169   
     
    152175  # If the second parameter is left off, then Dependencies will construct a set 
    153176  # of names that the file at +path+ may define. See 
    154   # +autoloadable_constants_for_path+ for more details. 
    155   def load_file(path, const_paths = autoloadable_constants_for_path(path)) 
     177  # +loadable_constants_for_path+ for more details. 
     178  def load_file(path, const_paths = loadable_constants_for_path(path)) 
    156179    log_call path, const_paths 
    157      
    158180    const_paths = [const_paths].compact unless const_paths.is_a? Array 
    159181    undefined_before = const_paths.reject(&method(:qualified_const_defined?)) 
     
    193215    name_error = NameError.new("uninitialized constant #{qualified_name}") 
    194216     
    195     file_path = search_for_autoload_file(path_suffix) 
     217    file_path = search_for_file(path_suffix) 
    196218    if file_path && ! loaded.include?(File.expand_path(file_path)) # We found a matching file to load 
    197       require_or_load file_path, qualified_name 
     219      require_or_load file_path 
    198220      raise LoadError, "Expected #{file_path} to define #{qualified_name}" unless from_mod.const_defined?(const_name) 
    199221      return from_mod.const_get(const_name) 
    200     elsif autoloadable_module? path_suffix # Create modules for directories 
    201       mod = Module.new 
    202       from_mod.const_set const_name, mod 
    203       autoloaded_constants << qualified_name 
     222    elsif mod = autoload_module!(from_mod, const_name, qualified_name, path_suffix) 
    204223      return mod 
    205224    elsif (parent = from_mod.parent) && parent != from_mod && 
  • trunk/activesupport/test/dependencies_test.rb

    r4782 r4837  
    11require File.dirname(__FILE__) + '/abstract_unit' 
     2require 'pp' 
    23 
    34module ModuleWithMissing 
     
    1819    old_mechanism, Dependencies.mechanism = Dependencies.mechanism, :load 
    1920    dir = File.dirname(__FILE__) 
    20     prior_autoload_paths = Dependencies.autoload_paths 
    21     Dependencies.autoload_paths = from.collect { |f| "#{dir}/#{f}" } 
     21    prior_load_paths = Dependencies.load_paths 
     22    Dependencies.load_paths = from.collect { |f| "#{dir}/#{f}" } 
    2223    yield 
    2324  ensure 
    24     Dependencies.autoload_paths = prior_autoload_paths 
     25    Dependencies.load_paths = prior_load_paths 
    2526    Dependencies.mechanism = old_mechanism 
    2627  end 
     
    220221  end 
    221222   
    222   def test_autoloadable_constants_for_path_should_handle_empty_autoloads 
    223     assert_equal [], Dependencies.autoloadable_constants_for_path('hello') 
    224   end 
    225    
    226   def test_autoloadable_constants_for_path_should_handle_relative_paths 
     223  def test_loadable_constants_for_path_should_handle_empty_autoloads 
     224    assert_equal [], Dependencies.loadable_constants_for_path('hello') 
     225  end 
     226   
     227  def test_loadable_constants_for_path_should_handle_relative_paths 
    227228    fake_root = 'dependencies' 
    228229    relative_root = File.dirname(__FILE__) + '/dependencies' 
    229230    ['', '/'].each do |suffix| 
    230231      with_loading fake_root + suffix do 
    231         assert_equal ["A::B"], Dependencies.autoloadable_constants_for_path(relative_root + '/a/b') 
    232       end 
    233     end 
    234   end 
    235    
    236   def test_autoloadable_constants_for_path_should_provide_all_results 
     232        assert_equal ["A::B"], Dependencies.loadable_constants_for_path(relative_root + '/a/b') 
     233      end 
     234    end 
     235  end 
     236   
     237  def test_loadable_constants_for_path_should_provide_all_results 
    237238    fake_root = '/usr/apps/backpack' 
    238239    with_loading fake_root, fake_root + '/lib' do 
    239       root = Dependencies.autoload_paths.first 
    240       assert_equal ["Lib::A::B", "A::B"], Dependencies.autoloadable_constants_for_path(root + '/lib/a/b') 
    241     end 
    242   end 
    243    
    244   def test_autoloadable_constants_for_path_should_uniq_results 
     240      root = Dependencies.load_paths.first 
     241      assert_equal ["Lib::A::B", "A::B"], Dependencies.loadable_constants_for_path(root + '/lib/a/b') 
     242    end 
     243  end 
     244   
     245  def test_loadable_constants_for_path_should_uniq_results 
    245246    fake_root = '/usr/apps/backpack/lib' 
    246247    with_loading fake_root, fake_root + '/' do 
    247       root = Dependencies.autoload_paths.first 
    248       assert_equal ["A::B"], Dependencies.autoloadable_constants_for_path(root + '/a/b') 
     248      root = Dependencies.load_paths.first 
     249      assert_equal ["A::B"], Dependencies.loadable_constants_for_path(root + '/a/b') 
    249250    end 
    250251  end 
     
    301302  def test_file_search 
    302303    with_loading 'dependencies' do 
    303       root = Dependencies.autoload_paths.first 
    304       assert_equal nil, Dependencies.search_for_autoload_file('service_three') 
    305       assert_equal nil, Dependencies.search_for_autoload_file('service_three.rb') 
    306       assert_equal root + '/service_one.rb', Dependencies.search_for_autoload_file('service_one') 
    307       assert_equal root + '/service_one.rb', Dependencies.search_for_autoload_file('service_one.rb') 
    308     end 
    309   end 
    310    
    311   def test_file_search_uses_first_in_autoload_path 
     304      root = Dependencies.load_paths.first 
     305      assert_equal nil, Dependencies.search_for_file('service_three') 
     306      assert_equal nil, Dependencies.search_for_file('service_three.rb') 
     307      assert_equal root + '/service_one.rb', Dependencies.search_for_file('service_one') 
     308      assert_equal root + '/service_one.rb', Dependencies.search_for_file('service_one.rb') 
     309    end 
     310  end 
     311   
     312  def test_file_search_uses_first_in_load_path 
    312313    with_loading 'dependencies', 'autoloading_fixtures' do 
    313       deps, autoload = Dependencies.autoload_paths 
     314      deps, autoload = Dependencies.load_paths 
    314315      assert_match %r/dependencies/, deps 
    315316      assert_match %r/autoloading_fixtures/, autoload 
    316317       
    317       assert_equal deps + '/conflict.rb', Dependencies.search_for_autoload_file('conflict') 
     318      assert_equal deps + '/conflict.rb', Dependencies.search_for_file('conflict') 
    318319    end 
    319320    with_loading 'autoloading_fixtures', 'dependencies' do 
    320       autoload, deps = Dependencies.autoload_paths 
     321      autoload, deps = Dependencies.load_paths 
    321322      assert_match %r/dependencies/, deps 
    322323      assert_match %r/autoloading_fixtures/, autoload 
    323324       
    324       assert_equal autoload + '/conflict.rb', Dependencies.search_for_autoload_file('conflict') 
     325      assert_equal autoload + '/conflict.rb', Dependencies.search_for_file('conflict') 
    325326    end 
    326327     
     
    375376  def test_removal_from_tree_should_be_detected 
    376377    with_loading 'dependencies' do 
    377       root = Dependencies.autoload_paths.first 
     378      root = Dependencies.load_paths.first 
    378379      c = ServiceOne 
    379380      Dependencies.clear 
     
    396397  end 
    397398   
     399  def test_load_once_paths_do_not_add_to_autoloaded_constants 
     400    with_loading 'autoloading_fixtures' do 
     401      Dependencies.load_once_paths = Dependencies.load_paths.dup 
     402       
     403      assert ! Dependencies.autoloaded?("ModuleFolder") 
     404      assert ! Dependencies.autoloaded?("ModuleFolder::NestedClass") 
     405      assert ! Dependencies.autoloaded?(ModuleFolder) 
     406       
     407      ModuleFolder::NestedClass 
     408      assert ! Dependencies.autoloaded?(ModuleFolder::NestedClass) 
     409    end 
     410  ensure 
     411    Object.send(:remove_const, :ModuleFolder) if defined?(ModuleFolder) 
     412    Dependencies.load_once_paths = [] 
     413  end 
     414   
    398415end 
  • trunk/railties/CHANGELOG

    r4766 r4837  
    11*SVN* 
     2 
     3* Add Dependencies.load_once_paths. [Nicholas Seckar] 
    24 
    35* Updated to script.aculo.us 1.6.2 [Thomas Fuchs] 
  • trunk/railties/lib/initializer.rb

    r4762 r4837  
    127127    end 
    128128     
    129     # Set the paths from which Rails will automatically load source files. 
     129    # Set the paths from which Rails will automatically load source files, and 
     130    # the load_once paths. 
    130131    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 
     132      Dependencies.load_paths = configuration.autoload_paths.uniq 
     133      Dependencies.load_once_paths = configuration.load_once_paths.uniq 
     134       
     135      extra = Dependencies.load_once_paths - Dependencies.load_paths 
     136      unless extra.empty? 
     137        abort <<-end_error 
     138          load_once_paths must be a subset of the autoload_paths. 
     139          Extra items in load_once_paths: #{extra * ','} 
     140        end_error 
     141      end 
     142       
     143      # Freeze the arrays so future modifications will fail rather than do nothing mysteriously 
    133144      configuration.autoload_paths.freeze 
     145      configuration.load_once_paths.freeze 
    134146    end 
    135147     
     
    425437    attr_accessor :autoload_paths 
    426438     
     439    # An array of paths from which Rails will automatically load from only once. 
     440    # All elements of this array must also be in +autoload_paths+. 
     441    attr_accessor :load_once_paths 
     442     
    427443    # The log level to use for the default Rails logger. In production mode, 
    428444    # this defaults to <tt>:info</tt>. In development mode, it defaults to 
     
    457473      self.load_paths                   = default_load_paths 
    458474      self.autoload_paths               = default_autoload_paths 
     475      self.load_once_paths              = default_load_once_paths 
    459476      self.log_path                     = default_log_path 
    460477      self.log_level                    = default_log_level 
     
    595612        paths.concat Dir["#{root_path}/vendor/plugins/*/lib/"] 
    596613        paths.concat builtin_directories 
     614        paths.uniq 
     615      end 
     616       
     617      def default_load_once_paths 
     618        plugin_root = "#{root_path}/vendor/plugins/" 
     619        default_autoload_paths.select do |path| 
     620          path[0, plugin_root.length] == plugin_root # No begins_with yet 
     621        end 
    597622      end 
    598623