Class: RailsAiContext::Introspectors::RouteIntrospector
- Inherits:
-
Object
- Object
- RailsAiContext::Introspectors::RouteIntrospector
- Extended by:
- StaticTier
- Defined in:
- lib/rails_ai_context/introspectors/route_introspector.rb
Overview
Extracts route information from the Rails router including HTTP verb, path, controller#action, and route constraints.
Constant Summary collapse
- MAX_DRAW_DEPTH =
A drawn file can draw again. Rails allows it; this stops a cycle of symlinked or mutually-drawing files from walking forever.
5
Constants included from StaticTier
StaticTier::ALTERNATE_SOURCE, StaticTier::FILES_ONLY, StaticTier::KINDS, StaticTier::RUNTIME_ONLY
Instance Attribute Summary collapse
-
#app ⇒ Object
readonly
Returns the value of attribute app.
Instance Method Summary collapse
-
#call ⇒ Hash
Routes grouped by controller.
-
#initialize(app) ⇒ RouteIntrospector
constructor
A new instance of RouteIntrospector.
-
#static_call ⇒ Object
Static tier: answer route questions from config/routes.rb and the files it draws.
Methods included from StaticTier
answers_statically?, static_tier, static_tier_declared?, unavailable_reason, validate_static_tier!
Constructor Details
#initialize(app) ⇒ RouteIntrospector
Returns a new instance of RouteIntrospector.
17 18 19 |
# File 'lib/rails_ai_context/introspectors/route_introspector.rb', line 17 def initialize(app) @app = app end |
Instance Attribute Details
#app ⇒ Object (readonly)
Returns the value of attribute app.
15 16 17 |
# File 'lib/rails_ai_context/introspectors/route_introspector.rb', line 15 def app @app end |
Instance Method Details
#call ⇒ Hash
Returns routes grouped by controller.
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/rails_ai_context/introspectors/route_introspector.rb', line 22 def call routes = extract_routes root = routes.find { |r| r[:path] == "/" && r[:verb]&.include?("GET") } { # Merged, because that is how every surface that lists routes counts # them: Rails registers PATCH and PUT separately for one update # action, and a raw total here left the generated context files # quoting a grand total their own app-route number cannot reach. total_routes: Tools::BaseTool.dedupe_put_patch_routes(routes).size, by_controller: group_by_controller(routes), api_namespaces: detect_api_namespaces(routes), mounted_engines: detect_mounted_engines, # Everything routable that has no controller#action: Engine mounts # AND bare rack apps (propshaft's /assets mounts a Server instance, # which detect_mounted_engines' Class check can't see). unrouted_mounts: count_unrouted_mounts, root_route: root ? "#{root[:controller]}##{root[:action]}" : nil } rescue => e { error: e. } end |
#static_call ⇒ Object
Static tier: answer route questions from config/routes.rb and the files it draws. Output mirrors the runtime shape exactly so tools, resources, and serializers need no static-awareness of their own. Routes behind dynamic constructs (devise_for, draw, concerns) are counted in :dynamic_routes rather than fabricated.
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 |
# File 'lib/rails_ai_context/introspectors/route_introspector.rb', line 51 def static_call routes_path = File.join(app.root.to_s, "config", "routes.rb") return { error: "config/routes.rb not found in #{app.root}" } unless File.exist?(routes_path) records, mounts, files = walk_routes_file(routes_path) entries = records.select { |r| r[:type] == :route } # A followed `draw` is no longer unexpanded - its routes are in the # list above. Counting it would overstate what is missing by exactly # the number of files this pass just read. dynamic = records.count { |r| r[:type] == :dynamic && !r[:followed] } result = { # Merged, for the reason `call` gives above: a raw total here made the # generated files say "8 total" where rails_get_routes, which merges # for itself, said 7 on the same `resources :posts`. total_routes: Tools::BaseTool.dedupe_put_patch_routes(entries).size, by_controller: group_by_controller(entries), api_namespaces: static_api_namespaces(entries), mounted_engines: mounts.map { |m| { engine: m[:engine], path: m[:path] } }, root_route: static_root_route(entries), note: "Parsed statically from #{static_sources_phrase(files)} (app not booted)", confidence: Confidence::STATIC } result[:dynamic_routes] = dynamic if dynamic.positive? result rescue => e { error: e. } end |