Rails route to catch non-GET requests to root path

We needed to add a specific line into our routes.rb file to cover non-GET requests going to the root path.

For the longest time I’ve been adding a catch-all to the bottom of my routes.rb file to say “Can’t find an appropriate route? Have a 404”. A recent project highlighted a need to add a second line in order to properly catch non-GET requests to the root path.

Up until now I’ve been adding a line like this to the bottom of my routes.rb file;

match '*url' => 'errors#not_found', via: :all

This says “match any other URL via any HTTP verb and send it to the not_found action in the ErrorsController”.

Sorry, almost any other URL. I mistakenly thought that the * part would match the root URL too, so visiting /. It turns out it doesn’t.

I was seeing a lot of errors being logged that looked like rails No route matches [POST] "/" or rails No route matches [OPTIONS] "/".

In both cases, requests like POST /broken-url or OPTIONS /lol would be correctly picked up and handled by our catch-all.

The fix is to have another line just above our catch-all,focusing on just the root. So;

match '/' => 'errors#not_found', via: [:post, :put, :patch, :delete, :options]

The reason we don’t do a via: :all here is because in most Rails projects we want the root path to go somewhere via a GET request. Most routes.rb files will have a line that looks like;

root 'static#home'

If we got all the way to the bottom and that wasn’t accessed, throw an error we can track in our error logs.

Our final two lines now look like this;

match '/' => 'errors#not_found', via: [:post, :put, :patch, :delete, :options]
match '*url' => 'errors#not_found', via: :all

Recent posts View all


The best way to test model scopes in Rails

Learn about Rails scopes and how to best test them with both Rspec and Minitest


Finding out what called a Ruby method

A quick way to understand what is calling your code using the caller method