3

So we've got a legacy system that tracks places with IDs like "Europe/France/Paris", and I'm building a Rails facade to turn this into URLs like http:// foobar/places/Europe/France/Paris. This requirement is not negotiable, the number of possible levels in unlimited, and we can't escape the slashes.

Setting up routes.rb for http://foobar/places/Europe is trivial:

map.resources :places

...but http:// foobar/places/Europe/France complains "No action responded to Europe". I tried:

map.connect '/places/:id', :controller => 'places', :action => 'show' 

...but this gives the same result, as apparently the :id ends at the first '/'. How do I make the ID cover anything and everything after the "places"?

lambshaanxy
  • 22,552
  • 10
  • 68
  • 92

2 Answers2

6

Have a look at the Routing Guide for full documentation:

http://guides.rubyonrails.org/routing.html

Specifically section "4.9 Route Globbing".

But I think what you really want to do is declare your route like:

map.connect '/places/*id', :controller => 'places', :action => 'index'

Called with a URL like

/places/foo/bar/1

Yields a params[:id] => ["foo", "bar", "1"]

Which you could easily (re)join with "/" to yield the full string you want "foo/bar/1" (you will probably have to re-insert the leading slash manually.

That should get you going.

Cody Caughlan
  • 32,456
  • 5
  • 63
  • 68
  • Brilliant, that almost works! The only problem is that the content is now always rendered as HTML, even if I try to force it with a ".xml" suffix? I'm using the standard respond_to do |format| block. – lambshaanxy Dec 03 '09 at 06:23
  • It looks like route globbing with :format support is a known issue - that is, it doesnt work, as you found out. The bug / patch is here discussed here: http://bit.ly/5LICLH but it looks like its not in the current release of Rails. Since you have no control of the URL portion (the route) the best I can think of is adding a query string parameter (?format=xml or ?format=json) which you can detect in your controller and act accordingly. Otherwise, it looks like you're SOL – Cody Caughlan Dec 03 '09 at 19:25
0

I tweaked Cody's answer above slightly to come up with this:

map.place '/places/*id', :controller => 'places', :action => 'show'
map.connect '/places/*id.:format', :controller => 'places', :action => 'show'

By using map.place instead of map.connect, Rails knows what resource we're dealing with and generated place_url, place_path etc helpers correctly.

Now, the 2nd line should work but doesn't thanks to the bug above, so here's a workaround for places_controller.rb that manually splits the ID and sets the format, defaulting to XML:

id, suffix = params[:id].join('/').split('.') 
params[:format] = suffix ? suffix : "xml"
lambshaanxy
  • 22,552
  • 10
  • 68
  • 92