This project is archived and is in readonly mode.
Bad routing recognition with globbing/format/requirements
-
CancelProfileIsBroken
- Assigned user set to josh
- State changed from new to verified
- Title changed from "optimal formatted routes" breaks format requirements to Bad routing recognition with globbing/format/requirements
There are a couple of general issues tangled up together here. You can see both by looking at the route recognizer we build in this case:
def recognize(path, env = {}) if (match = /\A\/files(?:\/?\Z|\/(.*)(?:\/|(\.[^\/?\.]+)?)??)\Z/.match(path)) params = parameter_shell.dup params[:path] = PathSegment::Result.new_escaped((match[1] || "").split('/')) if (m = match[2]) params[:format] = URI.unescape(m.from(1)) end params end endTwo problems:
1) Because we use (.*) to match the globbed path, there will never be a match[2] here to match against the format
2) Even if we fixed that, this would still fail because the regex segment we generate for the format includes [^\/?.], causing it to only recognize formats without a dot in them - so .tar.gz will never been seen as a format in any route.
Both of these issues seem fairly intractable for the 2.3 cycle. It looks like changing the format recognition regexp segment to include [^\/?] would fix the second issue, but that causes test_irregular_id_with_no_requirements_should_raise_error(ResourcesTest) to fail - personally I'm not too happy about that test, but it documents existing behavior that we probably don't want to change.
For what it's worth, here's a patch with a bunch of tests to document the failures. In the current edge code, test_path_without_format_should_include_format_in_path passes and all the rest fail. I think in an ideal world all should pass.
-
josh
- Assigned user cleared.
-
Pratik
- State changed from verified to open
-
Robert Glaser
For me, globbed routes with an attached format parameter generally don't work:
map.article ':locale/*path.:format', :controller => "articles", :action => "show"The format parameter is always being concatenated to the last element of the path array.
-
Michael Koziarski
- Tag set to bugmash
-
Kieran P
+1 The patch applies cleanly to Rails 2.3 (2-3-stable) and Rails 3.0 (master).
-
Elise Huard
Mike's patch applies to master, and indeed, only test_path_without_format_should_include_format_in_path passes from the 5 proposed tests.
IMHO there's a link with #2478 :defaults not in path cause "No matching segment exists" error
-
Peter Abrahamsen
Bump for great justice; this is really annoying.
-
Andrew White
- State changed from open to resolved
- Assigned user set to Andrew White
This seems to be working now:
match '/:locale/*path.:format', :to => 'articles#show' # GET /en/this/is/a/long/path.html # => {"format"=>"html", "action"=>"show", "path"=>"this/is/a/long/path", "controller"=>"articles", "locale"=>"en"}Please update this ticket if it isn't working for you.
-
Dawid Fatyga
- Importance changed from to
Hello,
what about cases where
:formatis omitted? The route to/en/this/is/a/long/pathwill not matcharticles#showaction with:format => 'html'.Adding:
:defaults => { :format => 'html' }does not solve the problem. Also changing the
matchto:match '/:locale/*path(.:format)', :to => 'articles#show'The routes that work as expected (allows the optional format) should look like this:
match '/:locale/*path.:format', :to => 'articles#show' match '/:locale/*path', :to => 'articles#show', :as => "article"I am submitting a diff with failing tests to clarify my point.
Regards,
Dawid -
Andrew White
The problem with trying to make the format parameter optional is that glob parameter will eat up the format even if you set the parameter regexp to be non-greedy. You need a fixed item in the path to stop the glob matching - the following works:
match '/:locale/*category/:article(.:format)' => 'articles#show', :as => :article # Matches the following: # - /en/computers/apple # - /en/computers/apple.html # - /en/computers/apple.xml # - /en/computers/apple/macbook # - /en/computers/apple/macbook.html # - /en/computers/apple/macbook.xmlYou can make the category optional as well
match '/:locale/(*category)/:article(.:format)' => 'articles#show', :as => :articleYou don't need the format parameter - Rails will add that by default unless you pass :format => false.
