Road Closed. Diversion. Road signs.

Ben Wicks

Tidy Up Your Routes with Only

It is easy with Rails’ syntax for defining routes to make more URLs in your application available than you might intend to.

Instead of…

…using an open resources block in your routes:

resources :orders do
  resources :products
end

Use…

…the only and except options to limit the actions you’re generating:

resources :orders, except: %w[destroy] do
  resources :products, only: %w[show]
end

Why?

This is all about clarity, tidying up, and protecting against unexpected errors or security holes.

In the default, unrestricted, case all seven default routes are created. If a user calls a route that is defined but not used, Rails will attempt to call the relevent controller action, even if it doesn’t exist. This can lead to errors or, worse, unexpected behaviour.

Rails’s standardised naming (while great for our code organisation and structure) means routes can be guessed. The presence of a GET /orders/12345 route pointing to orders#show would imply the existance of a GET /orders route for orders#index, and more dangerously a PUT /orders/12345 route for orders#update.

Minimising the generated routes is another step in maintaining a secure, organised codebase.

In extremely large codebases, where there are a lot of routes with this issue, you might see a performance improvement by creating fewer routes, but you’d need a very big application before this will even be worth thinking about.

Why not?

This might not be a severe issue for your application. The benefits, purely from an organisational perspective, mean it’s worth casting an eye over your config/routes.rb file.

Last updated on December 6th, 2021