Add support for optional root segments containing slashes

Optional segments with a root scope need to have the leading slash
outside of the parentheses, otherwise the generated url will be empty.
However if the route has non-optional elements then the leading slash
needs to remain inside the parentheses otherwise the generated url
will have two leading slashes, e.g:

Blog::Application.routes.draw do
  get '/(:category)', :to => 'posts#index', :as => :root
  get '/(:category)/author/:name', :to => 'posts#author', :as => :author
end

$ rake routes
  root GET /(:category)(.:format)              posts#index
author GET (/:category)/author/:name(.:format) posts#author

This change adds support for optional segments that contain a slash,
allowing support for urls like /page/2 for the root path, e.g:

Blog::Application.routes.draw do
  get '/(page/:page)', :to => 'posts#index', :as => :root
end

$ rake routes
root GET /(page/:page)(.:format) posts#index

Fixes #7073
(cherry picked from commit d8745decaf59aad32aa2f09abdba99b8d0e48b31)
This commit is contained in:
Andrew White
2012-07-17 19:15:10 +01:00
parent e23ec4c79c
commit 71d274dbbb
2 changed files with 27 additions and 1 deletions

View File

@@ -238,7 +238,7 @@ module ActionDispatch
# for root cases, where the latter is the correct one.
def self.normalize_path(path)
path = Journey::Router::Utils.normalize_path(path)
path.gsub!(%r{/(\(+)/?}, '\1/') unless path =~ %r{^/\(+[^/]+\)$}
path.gsub!(%r{/(\(+)/?}, '\1/') unless path =~ %r{^/\(+[^)]+\)$}
path
end

View File

@@ -2755,3 +2755,29 @@ class TestNamedRouteUrlHelpers < ActionDispatch::IntegrationTest
end
end
class TestOptionalRootSegments < ActionDispatch::IntegrationTest
stub_controllers do |routes|
Routes = routes
Routes.draw do
get '/(page/:page)', :to => 'pages#index', :as => :root
end
end
def app
Routes
end
include Routes.url_helpers
def test_optional_root_segments
get '/'
assert_equal 'pages#index', @response.body
assert_equal '/', root_path
get '/page/1'
assert_equal 'pages#index', @response.body
assert_equal '1', @request.params[:page]
assert_equal '/page/1', root_path('1')
assert_equal '/page/1', root_path(:page => '1')
end
end