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 photo
and 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
If you are trending into paths unknown, you always have the safety of tests to help you out. Both Rails and RSpec have ways to test your application routes.
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.