# frozen_string_literal: true module Chusaku # Handles extracting information about the Rails project's routes. class Routes class << self # Example output: # # { # 'users' => { # 'edit' => [ # { verb: 'GET', path: '/users/:id', name: 'edit_user' } # ], # 'update' => [ # { verb: 'PATCH', path: '/users', name: 'edit_user' }, # { verb: 'PUT', path: '/users', name: 'edit_user' } # ] # }, # 'empanadas' => { # 'create' => [ # { verb: 'POST', path: '/empanadas', name: nil } # ] # } # } # # @return {Hash} - Routes hash def call routes = {} Rails.application.routes.routes.each do |route| controller, action = extract_controller_and_action_from(route) routes[controller] ||= {} routes[controller][action] ||= [] routes[controller][action].push(format_route(route)) end backfill_routes(routes) end private # Extract information of a given route. # # @param {ActionDispatch::Journey::Route} route - Route given by Rails # @return {Hash} - { verb: String, path: String, name: String } def format_route(route) { verb: route.verb, path: route.path.spec.to_s.gsub('(.:format)', ''), name: route.name } end # Given a routes hash, backfill entries that aren't already filled by # `Rails.application.routes`. # # @param {Hash} routes - Routes hash generated by this class # @return {Hash} - Backfilled routes hash def backfill_routes(routes) paths = {} routes.each do |_controller, actions| actions.each do |_action, data| data.each do |datum| paths[datum[:path]] ||= datum[:name] datum[:name] ||= paths[datum[:path]] end end end routes end # Given a route, extract the controller and action strings. # # @param {ActionDispatch::Journey::Route} route - Route instance # @return {Array} - [String, String] def extract_controller_and_action_from(route) defaults = route.defaults controller = defaults[:controller] action = defaults[:action] [controller, action] end end end end