From 40b40c487040d9c721d486e8ec8cfbc53a8cd79a Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Wed, 26 Nov 2008 15:57:36 +0100 Subject: [PATCH] Added support for multiple routes files and made draw not clear the map so they can be additive --- .../action_controller/routing/route_set.rb | 54 ++++++++++++++----- actionpack/test/controller/routing_test.rb | 29 ++++++++-- 2 files changed, 67 insertions(+), 16 deletions(-) diff --git a/actionpack/lib/action_controller/routing/route_set.rb b/actionpack/lib/action_controller/routing/route_set.rb index 89cdf9d0f5662..a9690d180796c 100644 --- a/actionpack/lib/action_controller/routing/route_set.rb +++ b/actionpack/lib/action_controller/routing/route_set.rb @@ -200,9 +200,11 @@ def formatted_#{selector}(*args) end end - attr_accessor :routes, :named_routes, :configuration_file + attr_accessor :routes, :named_routes, :configuration_files def initialize + self.configuration_files = [] + self.routes = [] self.named_routes = NamedRouteCollection.new @@ -216,7 +218,6 @@ def builder end def draw - clear! yield Mapper.new(self) install_helpers end @@ -240,8 +241,22 @@ def empty? routes.empty? end + def add_configuration_file(path) + self.configuration_files << path + end + + # Deprecated accessor + def configuration_file=(path) + add_configuration_file(path) + end + + # Deprecated accessor + def configuration_file + configuration_files + end + def load! - Routing.use_controllers! nil # Clear the controller cache so we may discover new ones + Routing.use_controllers!(nil) # Clear the controller cache so we may discover new ones clear! load_routes! end @@ -250,24 +265,39 @@ def load! alias reload! load! def reload - if @routes_last_modified && configuration_file - mtime = File.stat(configuration_file).mtime - # if it hasn't been changed, then just return - return if mtime == @routes_last_modified - # if it has changed then record the new time and fall to the load! below - @routes_last_modified = mtime + if configuration_files.any? && @routes_last_modified + if routes_changed_at == @routes_last_modified + return # routes didn't change, don't reload + else + @routes_last_modified = routes_changed_at + end end + load! end def load_routes! - if configuration_file - load configuration_file - @routes_last_modified = File.stat(configuration_file).mtime + if configuration_files.any? + configuration_files.each { |config| load(config) } + @routes_last_modified = routes_changed_at else add_route ":controller/:action/:id" end end + + def routes_changed_at + routes_changed_at = nil + + configuration_files.each do |config| + config_changed_at = File.stat(config).mtime + + if routes_changed_at.nil? || config_changed_at > routes_changed_at + routes_changed_at = config_changed_at + end + end + + routes_changed_at + end def add_route(path, options = {}) route = builder.build(path, options) diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index d62c7a1743027..d5b6bd6b2a6e3 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -747,12 +747,16 @@ def setup ActionController::Base.optimise_named_routes = true @rs = ::ActionController::Routing::RouteSet.new - @rs.draw {|m| m.connect ':controller/:action/:id' } ActionController::Routing.use_controllers! %w(content admin/user admin/news_feed) end + + def teardown + @rs.clear! + end def test_default_setup + @rs.draw {|m| m.connect ':controller/:action/:id' } assert_equal({:controller => "content", :action => 'index'}, rs.recognize_path("/content")) assert_equal({:controller => "content", :action => 'list'}, rs.recognize_path("/content/list")) assert_equal({:controller => "content", :action => 'show', :id => '10'}, rs.recognize_path("/content/show/10")) @@ -769,6 +773,7 @@ def test_default_setup end def test_ignores_leading_slash + @rs.clear! @rs.draw {|m| m.connect '/:controller/:action/:id'} test_default_setup end @@ -1002,6 +1007,8 @@ def test_named_route_with_regexps end def test_changing_controller + @rs.draw {|m| m.connect ':controller/:action/:id' } + assert_equal '/admin/stuff/show/10', rs.generate( {:controller => 'stuff', :action => 'show', :id => 10}, {:controller => 'admin/user', :action => 'index'} @@ -1155,10 +1162,12 @@ def test_route_with_text_default end def test_action_expiry + @rs.draw {|m| m.connect ':controller/:action/:id' } assert_equal '/content', rs.generate({:controller => 'content'}, {:controller => 'content', :action => 'show'}) end def test_recognition_with_uppercase_controller_name + @rs.draw {|m| m.connect ':controller/:action/:id' } assert_equal({:controller => "content", :action => 'index'}, rs.recognize_path("/Content")) assert_equal({:controller => "content", :action => 'list'}, rs.recognize_path("/ConTent/list")) assert_equal({:controller => "content", :action => 'show', :id => '10'}, rs.recognize_path("/CONTENT/show/10")) @@ -2399,13 +2408,13 @@ class RouteLoadingTest < Test::Unit::TestCase def setup routes.instance_variable_set '@routes_last_modified', nil silence_warnings { Object.const_set :RAILS_ROOT, '.' } - ActionController::Routing::Routes.configuration_file = File.join(RAILS_ROOT, 'config', 'routes.rb') + routes.add_configuration_file(File.join(RAILS_ROOT, 'config', 'routes.rb')) @stat = stub_everything end def teardown - ActionController::Routing::Routes.configuration_file = nil + ActionController::Routing::Routes.configuration_files.clear Object.send :remove_const, :RAILS_ROOT end @@ -2448,12 +2457,24 @@ def test_adding_inflections_forces_reload end def test_load_with_configuration - routes.configuration_file = "foobarbaz" + routes.configuration_files.clear + routes.add_configuration_file("foobarbaz") File.expects(:stat).returns(@stat) routes.expects(:load).with("foobarbaz") routes.reload end + + def test_load_multiple_configurations + routes.add_configuration_file("engines.rb") + + File.expects(:stat).at_least_once.returns(@stat) + + routes.expects(:load).with('./config/routes.rb') + routes.expects(:load).with('engines.rb') + + routes.reload + end private def routes