REST principles by default is a fantastic convention within Rails applications. The documentation for how to route HTTP requests are comprehensive and give examples about
photo resources within an application. If you’ve got
tag as first class resources of your application, Rails has you covered. But what if you are building an application with a focus on one type of resource, do you really want
/resource_type as a prefix to all of your application paths? I certainly don’t and I’ll show you how to remove that without diverging from Rails core strenghts.
For better or worse, I’m always conscience of making sure applications I’m involved in have Cool URIs and sometimes that does mean fighting the Rails conventions. However Rails routing is very flexible and can provide me with the application paths that make me happy.
Take Twitter as an example. Every user has their username as a top level path, so instead of having
/users/robb1e, they simply have
/robb1e. When dealing with an application where there is one core resource it can make a lot of sense to strip the resource prefix. This can be achieved through
scopes in the routing configuration.
Your::Application.routes.draw do scope ":username" do get '', to: 'users#show' end end
Gives you routes which look like
GET /:username(.:format) users#show
If you wanted to see the followers and followees of that user, you have two options. Return to the default
resource or use HTTP verb contraints. I’ll show you both.
Your::Application.routes.draw do scope ":username" do get '', to: 'users#show' resource :following, only: [:show] resource :followers, only: [:show] end end
This adds the routes
following GET /:username/following(.:format) followings#show followers GET /:username/followers(.:format) followers#show
Alternatively HTTP verb constrains can be used to achieve a similar result.
Your::Application.routes.draw do scope ":username" do get '', to: 'users#show' get '/following', to: 'user#following' get '/followers', to: 'user#followers' end end
This gives the paths
GET /:username/following(.:format) user#following GET /:username/followers(.:format) user#followers
One gotcha which using the default resource routing removes is clashing paths. If you decide to build an admin page and want to put that at
/admin, that needs to be in the routes config before the scoped block and if a user has given themselves the name of
admin then you may be in for some fun.
So the next time a need arises for an unconventional route, check the documentation, it’s probably possible although almost always warants thinking about.
About the Author