---
title: "Identify unused Routes in Ruby on Rails"
description: "Identify unused routes in Ruby on Rails before 7.1 and after 7.1 with built-in tooling."
url: "https://qameta.com/posts/identify-unused-routes-in-ruby-on-rails/"
image: "https://qameta.com/posts/identify-unused-routes-in-ruby-on-rails/identify-unused-routes-in-ruby-on-rails.png"
---

# Identify unused Routes in Ruby on Rails

![Custom Rake Task: Identify unused routes in Ruby on Rails](https://qameta.com/posts/identify-unused-routes-in-ruby-on-rails/identify-unused-routes-in-ruby-on-rails.png)

Rails routes map URLs of a Ruby on Rails application to controller actions. As
a project grows, many new routes get added and older ones might become obsolete.
Cleanup of unused routes is a good practice to keep the codebase clean and
maintainable. This article shows how you can identify unused routes in Ruby on
Rails before 7.1 and after 7.1 with built-in tooling.


## Before Ruby on Rails 7.1

Before Ruby on Rails 7.1, there is no built-in tool to identify unused routes
in a project. However, some gems that can help you with this task like
[traceroute](https://github.com/amatsuda/traceroute) or a custom rake task like
this:

```ruby
# lib/tasks/routes_unused.rake
namespace :routes do
  desc "List unused routes"
  task unused: :environment do
    unused_routes = {}

    Rails.application.routes.routes.each do |route|
      controller_name = route.requirements[:controller].to_s.camelize
      controller_class = "#{controller_name}Controller"
      action = route.requirements[:action].to_s

      if Object.const_defined?(controller_class) &&
        !controller_class.constantize.new.respond_to?(action)
        controller = controller_class.constantize
        views_path = Rails.root.join("app", "views",
          controller.controller_path, "#{action}.*")
        unless Dir.glob(views_path).any?
          unused_routes[controller_class] = [] if unused_routes[controller].nil?
          unused_routes[controller_class] << action
        end
      end
    end

    unused_routes.each do |route, actions|
      actions.each do |action|
        p "#{route}##{action}"
      end
    end

    # return value 1 if there are unused routes to use it in CI/CD pipeline
    exit 1 if unused_routes.present?
  end
end
```

You can run this rake task with `bundle exec rake routes:unused` or `bin/rails
routes:unused`  to get a list of unused routes in your project.

The output will look like this:

```shell
$ bin/rails routes:unused
"UsersController#destroy"
```

This rake task has some limitations. It only checks if the controller and action
are both defined. If no action is determined, it will check for an existing
view file in the views folder with action as a name.

## After Ruby on Rails 7.1

With Ruby on Rails 7.1, a new command-line tool called `bin/rails routes
--unused` was added by [PR
rails#45701](https://github.com/rails/rails/pull/45701). It does the same as the
custom rake task above. You can run it with `bin/rails routes --unused` to get a
list of unused routes in your project:

```shell
$ bin/rails routes --unused
Found 1 unused route:

Prefix Verb   URI Pattern             Controller#Action
       DELETE /users/:id(.:format)    users#destroy
```

This command will output a list of unused routes in your project. It will show
the HTTP verb, the URI pattern, and the controller action of the unused route.

It is a great addition to the Ruby on Rails tooling and makes it easier to
identify unused routes in a Rails project. This is especially useful for
large projects with many routes or legacy projects being refactored.

## Limitations

As for both the custom rake task and the built-in command, there are some
limitations you have to consider:

- They only check if the controller and action or a view with the action name
  are defined.
- A missing controller will not be detected as the routes also have internal
  rails-specific routes like `rails/assets/...`. They are skipped this way.
- They do not check if the route is used in the application.
- The rake task and the command only check for routes that are defined. They do
  not find controllers or actions which are not addressed in the routes.
- Nested routes checking is not supported.

## Run in CI/CD Pipeline

You can use both commands as part of your CI/CD pipeline to ensure that no new
unused routes are added to the project helping developers. This can be also
added to a `bin/check` script, which runs all checks before pushing to the
repository.

The output in a Ruby on Rails 7.1 project or later will be:

```shell
$ bin/rails routes --unused
Found 1 unused route:

Prefix Verb   URI Pattern             Controller#Action
       DELETE /users/:id(.:format)    users#destroy

$ echo $?
1
```

For a Ruby on Rails project before 7.1 using my rake task, the output will be:

```shell
$ bin/rails routes:unused
"UsersController#destroy"

$ echo $?
1
```

## Conclusion

Identifying unused routes in a Ruby on Rails project is a good practice to keep
the codebase clean and maintainable. Before Ruby on Rails 7.1, you could use a
custom rake task or a gem like `traceroute` to identify unused routes. With Ruby
on Rails 7.1, you can use the built-in command `bin/rails routes --unused` to
get a list of unused routes in your project. This is especially useful for large
projects with many routes where it is hard to keep track of all routes manually.
