Class: RailsMcpInsight::Analyzers::RouteAnalyzer
- Inherits:
-
Object
- Object
- RailsMcpInsight::Analyzers::RouteAnalyzer
- Defined in:
- lib/rails_mcp_insight/analyzers/route_analyzer.rb
Overview
Parses config/routes.rb to extract all routes, supporting resources, namespaces, scopes, and individual route definitions.
Constant Summary collapse
- ROUTE_METHODS =
["get", "post", "put", "patch", "delete", "root", "match"].freeze
Instance Method Summary collapse
-
#analyze ⇒ Object
Returns all routes found in the routes file(s).
-
#initialize(config, ast_parser: AstParser.new) ⇒ RouteAnalyzer
constructor
A new instance of RouteAnalyzer.
-
#search(query: nil, method: nil) ⇒ Object
Search routes by query string (matches path or controller_action).
Constructor Details
#initialize(config, ast_parser: AstParser.new) ⇒ RouteAnalyzer
Returns a new instance of RouteAnalyzer.
10 11 12 13 |
# File 'lib/rails_mcp_insight/analyzers/route_analyzer.rb', line 10 def initialize(config, ast_parser: AstParser.new) @config = config @ast_parser = ast_parser end |
Instance Method Details
#analyze ⇒ Object
Returns all routes found in the routes file(s)
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/rails_mcp_insight/analyzers/route_analyzer.rb', line 16 def analyze routes = [] routes_file = @config.routes_file return routes unless File.exist?(routes_file) content = File.read(routes_file) lines = content.lines current_namespace = [] current_scope = [] lines.each_with_index do |line, idx| stripped = line.strip next if stripped.empty? || stripped.start_with?("#") # Track namespace/scope nesting if (match = stripped.match(/^\s*namespace\s+:(\w+)/)) current_namespace.push(match[1]) elsif (match = stripped.match(/^\s*scope\s+["']?([^"',\s]+)/)) current_scope.push(match[1].sub(%r{^/}, "")) end # Match resources/resource if (match = stripped.match(/^\s*resources?\s+:(\w+)/)) resource_name = match[1] prefix = build_prefix(current_namespace, current_scope) routes.concat(generate_resource_routes(resource_name, prefix, idx + 1, stripped.start_with?("resource "))) end # Match individual routes ROUTE_METHODS.each do |method| unless (match = stripped.match(/^\s*#{method}\s+["']([^"']+)["'](?:.*?(?:to:|=>)\s*["']([^"']+)["'])?/)) next end path = match[1] controller_action = match[2] prefix = build_prefix(current_namespace, current_scope) full_path = "/#{prefix}#{path}".gsub(%r{//+}, "/") routes << { method: method.upcase == "MATCH" ? "ANY" : method.upcase, path: full_path, controller_action: controller_action || infer_controller_action(path, method), line: idx + 1, source: "config/routes.rb" } end # Root route if (match = stripped.match(/^\s*root\s+(?:to:\s*)?["']([^"']+)["']/)) routes << { method: "GET", path: "/#{build_prefix(current_namespace, current_scope)}".gsub(%r{//+}, "/"), controller_action: match[1], line: idx + 1, source: "config/routes.rb" } end # Track end of blocks if stripped == "end" # Pop the most recent nesting (simplified — works for most cases) if current_namespace.length > current_scope.length current_namespace.pop unless current_namespace.empty? else current_scope.pop unless current_scope.empty? end end end routes end |
#search(query: nil, method: nil) ⇒ Object
Search routes by query string (matches path or controller_action)
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/rails_mcp_insight/analyzers/route_analyzer.rb', line 92 def search(query: nil, method: nil) all_routes = analyze results = all_routes if query query_downcase = query.downcase results = results.select do |route| route[:path].downcase.include?(query_downcase) || route[:controller_action]&.downcase&.include?(query_downcase) end end if method method_up = method.upcase results = results.select { |route| route[:method] == method_up } end results end |