Skip to content

Instantly share code, notes, and snippets.

@kivanio
Forked from strzibny/unused_routes.rb
Created May 23, 2022 12:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kivanio/62787f4ac00e8cbaae43a24ac2d2b497 to your computer and use it in GitHub Desktop.
Save kivanio/62787f4ac00e8cbaae43a24ac2d2b497 to your computer and use it in GitHub Desktop.
Find unused routes in Rails
#!/usr/bin/env ruby
# Extracted from traceroute gem + checking the presence of views as well
require_relative './config/environment.rb'
class Traceroute
def initialize(app)
@app = app
end
def load_everything!
@app.eager_load!
::Rails::InfoController rescue NameError
::Rails::WelcomeController rescue NameError
::Rails::MailersController rescue NameError
@app.reload_routes!
Rails::Engine.subclasses.each(&:eager_load!)
end
def unused_routes
views = Dir.glob("#{Rails.root}/app/views/**/*").each do |view|
view.gsub!(/(.*\/[^\/\.]+)[^\/]+/, '\\1')
end
(routed_actions - defined_action_methods).reject do |path|
views.include? "#{Rails.root}/app/views/#{path.gsub('#','/')}"
end
end
def defined_action_methods
ActionController::Base.descendants.map do |controller|
controller.action_methods.reject {|a| (a =~ /\A(_conditional)?_callback_/) || (a == '_layout_from_proc')}.map do |action|
"#{controller.controller_path}##{action}"
end
end.flatten.reject {|r| r.start_with? 'rails/'}
end
def routed_actions
routes.map do |r|
if r.requirements[:controller].blank? && r.requirements[:action].blank? && (r.path == '/:controller(/:action(/:id(.:format)))')
%Q["#{r.path}" This is a legacy wild controller route that's not recommended for RESTful applications.]
else
"#{r.requirements[:controller]}##{r.requirements[:action]}"
end
end.reject {|r| r.start_with? 'rails/'}
end
private
def routes
routes = @app.routes.routes.reject {|r| r.name.nil? && r.requirements.blank?}
routes.reject! {|r| r.app.is_a?(ActionDispatch::Routing::Mapper::Constraints) && r.app.app.respond_to?(:call)}
routes.reject! {|r| r.app.is_a?(ActionDispatch::Routing::Redirect)}
if @app.config.respond_to?(:assets)
exclusion_regexp = %r{^#{@app.config.assets.prefix}}
routes.reject! do |route|
path = (defined?(ActionDispatch::Journey::Route) || defined?(Journey::Route)) ? route.path.spec.to_s : route.path
path =~ exclusion_regexp
end
end
routes
end
end
traceroute = Traceroute.new Rails.application
traceroute.load_everything!
unused_routes = traceroute.unused_routes
puts "Unused routes (#{unused_routes.count}):"
unused_routes.each {|route| puts " #{route}"}
unless unused_routes.empty? || ENV['FAIL_ON_ERROR'].blank?
fail "Unused routes detected."
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment