Compare Rails routes. The quick way.

With time and practice I found out that usage of additional shortcuts available in Rails for routing (such as resources, or member , or collection ) usually makes more damage than good. Especially when project grows up and file config/routes.rb become pretty nice and self documented way to find out which endpoints are available and what goes where.

Image for post
Image for post

In addition to my native feelings about such shortcuts recently I got a task which required separation of available endpoints on “read” and “write”. It was needed to put them under different constraints in URL-s. As a result, for every resource :something actions index / show were supposed to go here and create / update / delete — there. Service had not so many routes so I splitted them by hands. Code review went well. All tests passed. But who believes that green tests are guarantee for production well being will never sleep well at night, right? So, I decided to write a script which will check everything for me.

First of all I was thinking about ability of standard rake routes to print routes in some consumable way, like CSV or JSON. But as I quickly found out it’s printing only standard view you are used to see in console or a little bit extended version of it. Here is a source code of the task on Github. On the other hand, after some thoughts the way this task has been built is pretty nice because formatter logic was extracted into separated class. So, we can’t make rake routes do the job for us, but still can print CSV file we need without too much job.

Sadly, class which incapsulates formatting logic has no formal abstract definition, but as far as I understand from quick overview of existing implementations the interface assumption looks like this:

So, if we want to receive CSV representation here is how our formatter will look like:

Now we apply it using Rails console, take routes and save them into separated output CSV file:

Good. With such script we can easily checkout old version of code before our changes and take snapshots of all routes into the file. Let’s say /tmp/old_routes.csv. After it switch to the new branch and take another one snapshot, after changes. Let’s say /tmp/new_routes.csv. Nice.

The only one step left is comparison. What do we want to check:

  1. All routes which were in old version of code are presented in new version and points to the same endpoint (controller and action).
  2. No new routes were added.

In order to check it we need to: read both files, put routes into some data structure which is easy to compare and print out the difference. I decided to go easy and store routes in a Hash where key is a verb (GET, POST , PUT , PATCH or DELETE ) and value is a set of mapping from path into endpoints. Something like:

If you have such representation it’s only needed to check that (old sets - new sets ) + (new sets - old sets) is empty set. Got it? Let’s code:

That’s it. Now you can take the output, pretty print it somehow (I used but there are many ways) and compare (may be done in automated way as well, for sure).

Have fun and let me know if you think that ability to print routes in some processable format like CSV or JSON using rake routes worth PR into Rails. I’m considering it.

P.S. As a result, I found one route with typo this way, so it’s never bad idea to check twice! 😉

Written by

Let's get it up and running 👌

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store