Routing parameters with a dot

Posted by Andreas on Tuesday, May 05, 2009 at 07:35 (CEST)

Last week I received an interesting bug report for an application I’m working on at the office. It has a controller with an index action that displays a list of items which can be filtered by tags. A tester reported that every time he chooses to filter the list by a tag that contains a dot, the site returns an error. First this seems strange since tags with a dot worked perfectly fine in tests.

But after digging deeper, I found a surprising reason for this strange error: To make URLs look nicer, I defined an extra route like this:

1 map.things 'things/:tag', :controller => 'things', :action => 'index',
2   :tag => nil

The intention was, to have /things/foo instead of /things&tag=foo as the URL. This actually worked fine – except for cases when the tag contained a dot.

Rails seems to magically append :format to every rule so that different result formats are possible with one rule (like /things.html and /things.json). If a tag contained a dot, the URL requested was /items/foo.bar, which Rails parsed into :tag => 'foo', :format => 'bar'.

So the controller’s index action was requested to display all entries for tag foo and output results in format bar – which is unknown and unsupported and therefore resulted in an error page.

This behaviour seems to be hardcoded into Rails and I couldn’t find a way to disable it. But luckily a workaround is pretty easy. The trick is to make the tag parameter’s regular expression greedy, so that it covers the format part as well. Using the :requirements option to a route, we can set the regexp for a parameter:

1 map.things 'things/:tag', :controller => 'things', :action => 'index',
2   :tag => nil, :requirements => { :tag => /.+/ }

Now it works as intended. :format is always ignored now and the whole string is put into params[:tag].

• Tags: ,
CommentsPermalink
blog comments powered by Disqus