RESTful routing: allowing .s [dots] in ids


#1

Hi Folks,

I’m trying to set up a RESTful route in my rails app and have hit a
snag. My application allows various different types of querying centered
around a search phrase, and I decided it’d be nice to that in my RESTful
API by exposing resources like:

http://www.myapp.com/api/keyword_research/SOME_SEARCH_PHRASE
for basic information about the phrase, and then

http://www.myapp.com/api/keyword_research/SOME_SEARCH_PHRASE/popularity
for a specific query on that phrase (it’s popularity in this case).

Essentially I’m trying to represent the search space as a resource
space, with one resource for each possible phrase.

I set up the following in my routes.rb, and it ALMOST works:

map.resources(
:keyword_research,
:controller => ‘api/v3/keyword_research’ ,
:member => {:index => :get, :popularity => :get }
)

I can then use something like the following to generate resource URLs:
keyword_research_url( ‘some search phrase’ )
and
popularity_keyword_research_url( ‘some search phrase’ )

The only problem is when the search phrase contains a dot. That leads to
urls like:

http://www.myapp.com/api/keyword_research/PHRASE.WITH.DOTS
and
http://www.myapp.com/api/keyword_research/PHRASE.WITH.DOTS/popularity

which confuses the routing system to no end. This results in various
errors such as template missing, no route found, etc etc. Essentially I
think the routing system is interpretting the dotted id as specifying a
representation type, or something similar.

I thought a nice solution would be to encode the search_phrase portion
of these resource urls when I generate them, leading to urls like:
http://www.myapp.com/api/keyword_research/PHRASE.WITH.DOTS
and
http://www.myapp.com/api/keyword_research/PHRASE.WITH.DOTS/popularity

I’ve tested urls encoded like this and they appear to play nicely with
the routing I have, and are within the specs AFAIK. I’d be happy with
this, but the problem is that I don’t know how to generate urls like
this using the url helper methods.

Anyone have any ideas? I’d be open to either a clean way to support
un-encoded dots, or some advice on how to get ids with the dots encoded
out of the url helpers. Or some other elegant solution, of course!

Thanks,
Pete


#2

See http://dev.rubyonrails.org/ticket/6426.

One solution is to add
module ActionController::Routing
SEPARATORS = %w( / ; , ? )
end
in your controller. I’m not sure if this still works under recent
versions of Rails.

Lee

On Dec 9, 3:42 pm, Pete H. removed_email_address@domain.invalid


#3

I haven’t tried it with a restful route, but I have a route like this:

 r.curriculum '/curriculum/:code/:title/:action',
              :defaults => { :action => 'overview' },
              :requirements => { :code => %r([\d.]+) }

:code is a float-like number. 11.123, etc. The above :requirements
part let’s digits/dots through. Before I added that my memory is it
complained like you say.

Perhaps you can work that into the restful route somehow…


#4

Lee F. wrote:

See http://dev.rubyonrails.org/ticket/6426.

One solution is to add
module ActionController::Routing
SEPARATORS = %w( / ; , ? )
end
in your controller. I’m not sure if this still works under recent
versions of Rails.

Lee

On Dec 9, 3:42�pm, Pete H. removed_email_address@domain.invalid

Thanks Lee, but like Philip’s solution this also doesn’t allow API
clients to specify a format by appending a .xml (or .html or .csv or
whatever).


#5

Philip H. wrote:

I haven’t tried it with a restful route, but I have a route like this:

 r.curriculum '/curriculum/:code/:title/:action',
              :defaults => { :action => 'overview' },
              :requirements => { :code => %r([\d.]+) }

:code is a float-like number. 11.123, etc. The above :requirements
part let’s digits/dots through. Before I added that my memory is it
complained like you say.

Perhaps you can work that into the restful route somehow…

Thanks Philip, I tried this tack but it doesn’t work with a url where
the id is at the end. If we have a path like:

/curriculum/12.1

the routing can’t distinguish between id 12 with a format of 1 and an id
of 12.1. This is compounded by the fact that my API clients need to be
able to tack .xml on to the end of urls when they need an xml
representation.

:frowning: