Use Canonical Routes to Conform Rails’ Defaults

Learn about routes that we should use in Rails applications.

What are routes used for?

Routes serve two purposes. Their primary purpose is to connect the view to the controller layer. Routes tell us what code will be triggered when an HTTP request is made to a URL. The second (and unfortunate) purpose of routes is as a user interface element. URLs tend to show up directly in social media, search results, and even newspaper articles. This means that a user will see them and that they matter.

It can be hard to design routes that serve both purposes. If our routes are designed first around aesthetic concerns, we’ll quickly have a sea of inconsistent and confusing URLs, and this will create a carrying cost on the team every time a new feature has to be added. We also can’t insist that our app is only available with conventional Rails routes. Imagine someone reading a podcast ad with a database ID in it!

However, the marketing department isn’t the only source of complexity with our routes. The more routes we add and the more features our app supports, the harder it can be to keep the routes organized. If routes become messy, inconsistent, or hard to understand, it adds carrying costs with every new feature we want to implement. Fortunately, with a bit of discipline and a few simple techniques, we can keep our routes file easy to navigate and understand and still provide the necessary user-friendly URLs if they are called for.

The five conventions that will help us are:

  • Always use canonical routes that conform to Rails’ defaults.
  • Never configure a route in config/routes.rb that is not being used.
  • User-friendly URLs should be added in addition to the canonical routes.
  • Avoid custom actions in favor of creating new resources that use Rails’ default actions.
  • Use nested routes strategically.

Let’s dig into each of these to learn how they help sustainability.

Setting up routes

With just a single line of code, Rails sets up eight routes (seven actions) for a given resource.

resources :widgets

This simple declaration in config/routes.rb is the basis for consistency that provides a lot of leverage. We get URL helpers to generate canonical URLs without string-building, a clear and easy-to-understand connection to our controllers, and some nice documentation that is available via bin/rails routes. If the app’s routes are made up entirely of calls to resources, it becomes easy to understand the app at a high level. Developers can begin each feature by identifying the right resource and choosing which of the seven conventional actions needs to be supported. It also means that looking at the URL of a browser is all we need to figure out what code is triggering the view we’re seeing.

Even though it might not seem like a major architectural decision, sticking with Rails conventions for routing can reduce real friction during development. Let’s make two routes: one will be conventional using resources, and the other will diverge from this standard and use get. The first route will be for showing the information about a given widget. We’ll add the widgets resource to config/routes.rb:

Get hands-on with 1200+ tech skills courses.