Skip to content

Commit

Permalink
Added support for multiple routes files and made draw not clear the m…
Browse files Browse the repository at this point in the history
…ap so they can be additive
  • Loading branch information
dhh committed Nov 26, 2008
1 parent 63d8f56 commit 40b40c4
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 16 deletions.
54 changes: 42 additions & 12 deletions actionpack/lib/action_controller/routing/route_set.rb
Expand Up @@ -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

Expand All @@ -216,7 +218,6 @@ def builder
end

def draw
clear!
yield Mapper.new(self)
install_helpers
end
Expand All @@ -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
Expand All @@ -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)
Expand Down
29 changes: 25 additions & 4 deletions actionpack/test/controller/routing_test.rb
Expand Up @@ -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"))
Expand All @@ -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
Expand Down Expand Up @@ -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'}
Expand Down Expand Up @@ -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"))
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down

1 comment on commit 40b40c4

@wkonkel
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here’s another approach (which is additive to this commit, not contradictory) for routing from plugins:

http://blog.hungrymachine.com/2008/11/26/acts_as_routing-modular-routing-in-rails-and-merb

Please sign in to comment.