Identify unused Routes in Ruby on Rails
Reading time: 4 minutes
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 or a custom rake task like this:
# 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:
$ 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. 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:
$ 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:
$ 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:
$ 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.
Newsletter
See Also
- Working with Legacy Ruby on Rails: spring.gem fork() Crash
- Use Geocoder and MaxMind DB to Geocode IP Addresses
- Analyzing SassC::SyntaxError in Ruby on Rails 7.0
- Deploy Ruby on Rails 7.0 to Dokku micro PaaS
- Fixing require LoadError as an example for the matrix gem