routes-analyzer 0.1.2 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/README.md +53 -29
 - data/lib/routes/analyzer/middleware.rb +9 -11
 - data/lib/routes/analyzer/route_usage_tracker.rb +31 -25
 - data/lib/routes/analyzer/version.rb +1 -1
 - data/lib/tasks/routes/analyzer_tasks.rake +24 -25
 - metadata +1 -1
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 3cae3e4dca655b13929955c6357b4351607dd32ae29331c643666e6d05562e32
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 3b533755ae2bc4b810708ac9d705085f5467c3cb94714a458baa6aaa8f5eaebf
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: d47e92d852c70f7ce7108777532aea5f5650f562fe31607d522b178bc206ed8430f713408cb8e28989d38ff8c66c3c5f64bf4ac87407e928bff9f450b7189255
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: d3c981912a2b4894895f4f19d80842d878f6aa1edb1ec157a34e05d54e8ef67cd7c490ed055ef7d1bfd8187277e0f4d7eb923d52d127669eeaedcdcf3dea8a03
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -2,14 +2,15 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            [](https://badge.fury.io/rb/routes-analyzer)
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
            A Ruby on Rails plugin that tracks and analyzes  
     | 
| 
      
 5 
     | 
    
         
            +
            A Ruby on Rails plugin that tracks and analyzes controller action usage in your application. It uses Redis to store action access patterns and provides insights into which controller actions are being used and which are not.
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
            ## Features
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
            - ** 
     | 
| 
      
 9 
     | 
    
         
            +
            - **Controller Action Tracking**: Automatically tracks which controller actions are accessed and how often
         
     | 
| 
      
 10 
     | 
    
         
            +
            - **Method-Agnostic Tracking**: Actions are tracked by controller#action regardless of HTTP method (GET, POST, etc.)
         
     | 
| 
       10 
11 
     | 
    
         
             
            - **Redis Storage**: Uses Redis to store usage statistics efficiently  
         
     | 
| 
       11 
12 
     | 
    
         
             
            - **Configurable Timeframe**: Set custom analysis periods (default 30 days)
         
     | 
| 
       12 
     | 
    
         
            -
            - **Comprehensive Reporting**: Shows both used and unused  
     | 
| 
      
 13 
     | 
    
         
            +
            - **Comprehensive Reporting**: Shows both used and unused controller actions
         
     | 
| 
       13 
14 
     | 
    
         
             
            - **Rake Tasks**: Easy-to-use commands for viewing statistics and managing data
         
     | 
| 
       14 
15 
     | 
    
         | 
| 
       15 
16 
     | 
    
         
             
            ## Installation
         
     | 
| 
         @@ -40,10 +41,10 @@ Routes::Analyzer.configure do |config| 
     | 
|
| 
       40 
41 
     | 
    
         
             
              # Redis connection URL
         
     | 
| 
       41 
42 
     | 
    
         
             
              config.redis_url = ENV['REDIS_URL'] || 'redis://localhost:6379/0'
         
     | 
| 
       42 
43 
     | 
    
         | 
| 
       43 
     | 
    
         
            -
              # Redis key prefix for storing  
     | 
| 
      
 44 
     | 
    
         
            +
              # Redis key prefix for storing action usage data
         
     | 
| 
       44 
45 
     | 
    
         
             
              config.redis_key_prefix = 'routes_analyzer'
         
     | 
| 
       45 
46 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
              # Timeframe for  
     | 
| 
      
 47 
     | 
    
         
            +
              # Timeframe for action usage analysis in days
         
     | 
| 
       47 
48 
     | 
    
         
             
              config.timeframe = 30
         
     | 
| 
       48 
49 
     | 
    
         
             
            end
         
     | 
| 
       49 
50 
     | 
    
         
             
            ```
         
     | 
| 
         @@ -58,38 +59,39 @@ Alternatively, you can create the configuration file manually in `config/initial 
     | 
|
| 
       58 
59 
     | 
    
         | 
| 
       59 
60 
     | 
    
         
             
            ## Usage
         
     | 
| 
       60 
61 
     | 
    
         | 
| 
       61 
     | 
    
         
            -
            Once installed and configured, the middleware will automatically start tracking  
     | 
| 
      
 62 
     | 
    
         
            +
            Once installed and configured, the middleware will automatically start tracking controller action usage. No additional code changes are required.
         
     | 
| 
       62 
63 
     | 
    
         | 
| 
       63 
64 
     | 
    
         
             
            ### Rake Tasks
         
     | 
| 
       64 
65 
     | 
    
         | 
| 
       65 
     | 
    
         
            -
            #### View  
     | 
| 
      
 66 
     | 
    
         
            +
            #### View Controller Action Usage Statistics
         
     | 
| 
       66 
67 
     | 
    
         | 
| 
       67 
68 
     | 
    
         
             
            ```bash
         
     | 
| 
       68 
69 
     | 
    
         
             
            bundle exec rake routes:analyzer:usage
         
     | 
| 
       69 
70 
     | 
    
         
             
            ```
         
     | 
| 
       70 
71 
     | 
    
         | 
| 
       71 
72 
     | 
    
         
             
            This command shows:
         
     | 
| 
       72 
     | 
    
         
            -
            - All  
     | 
| 
       73 
     | 
    
         
            -
            - Usage count for each  
     | 
| 
      
 73 
     | 
    
         
            +
            - All controller actions available in your application
         
     | 
| 
      
 74 
     | 
    
         
            +
            - Usage count for each action in the specified timeframe
         
     | 
| 
       74 
75 
     | 
    
         
             
            - Last access timestamp
         
     | 
| 
       75 
     | 
    
         
            -
            - Summary statistics (total, used, unused  
     | 
| 
      
 76 
     | 
    
         
            +
            - Summary statistics (total, used, unused actions)
         
     | 
| 
       76 
77 
     | 
    
         | 
| 
       77 
78 
     | 
    
         
             
            Example output:
         
     | 
| 
       78 
79 
     | 
    
         
             
            ```
         
     | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
      
 80 
     | 
    
         
            +
            Controller Action Usage Analysis (30 days)
         
     | 
| 
       80 
81 
     | 
    
         
             
            ================================================================================
         
     | 
| 
       81 
82 
     | 
    
         | 
| 
       82 
     | 
    
         
            -
            COUNT     
     | 
| 
      
 83 
     | 
    
         
            +
            COUNT    CONTROLLER#ACTION                        METHOD          LAST ACCESSED
         
     | 
| 
       83 
84 
     | 
    
         
             
            --------------------------------------------------------------------------------
         
     | 
| 
       84 
     | 
    
         
            -
            45        
     | 
| 
       85 
     | 
    
         
            -
            23        
     | 
| 
       86 
     | 
    
         
            -
            12        
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
       88 
     | 
    
         
            -
            0        / 
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
      
 85 
     | 
    
         
            +
            45       users#index                              GET             2025-06-18 14:30
         
     | 
| 
      
 86 
     | 
    
         
            +
            23       users#show                               GET             2025-06-18 12:15
         
     | 
| 
      
 87 
     | 
    
         
            +
            12       posts#index                              GET             2025-06-17 09:45
         
     | 
| 
      
 88 
     | 
    
         
            +
            5        posts#create                             POST            2025-06-16 16:20
         
     | 
| 
      
 89 
     | 
    
         
            +
            0        admin/reports#index                      GET             Never
         
     | 
| 
      
 90 
     | 
    
         
            +
            0        api/v1/health#check                      GET             Never
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
            Total actions: 6
         
     | 
| 
      
 93 
     | 
    
         
            +
            Used actions: 4
         
     | 
| 
      
 94 
     | 
    
         
            +
            Unused actions: 2
         
     | 
| 
       93 
95 
     | 
    
         
             
            ```
         
     | 
| 
       94 
96 
     | 
    
         | 
| 
       95 
97 
     | 
    
         
             
            #### Clear Usage Data
         
     | 
| 
         @@ -98,7 +100,7 @@ Unused routes: 2 
     | 
|
| 
       98 
100 
     | 
    
         
             
            bundle exec rake routes:analyzer:clear
         
     | 
| 
       99 
101 
     | 
    
         
             
            ```
         
     | 
| 
       100 
102 
     | 
    
         | 
| 
       101 
     | 
    
         
            -
            Removes all stored  
     | 
| 
      
 103 
     | 
    
         
            +
            Removes all stored controller action usage data from Redis.
         
     | 
| 
       102 
104 
     | 
    
         | 
| 
       103 
105 
     | 
    
         
             
            #### Check Configuration
         
     | 
| 
       104 
106 
     | 
    
         | 
| 
         @@ -111,13 +113,13 @@ Displays current configuration and tests Redis connectivity. 
     | 
|
| 
       111 
113 
     | 
    
         
             
            ## How It Works
         
     | 
| 
       112 
114 
     | 
    
         | 
| 
       113 
115 
     | 
    
         
             
            1. **Middleware Integration**: The plugin automatically adds middleware to your Rails application
         
     | 
| 
       114 
     | 
    
         
            -
            2. ** 
     | 
| 
      
 116 
     | 
    
         
            +
            2. **Controller Action Filtering**: Only controller actions from defined routes in `routes.rb` are tracked. This ensures that:
         
     | 
| 
       115 
117 
     | 
    
         
             
               - Undefined routes (404 errors) are not tracked
         
     | 
| 
       116 
118 
     | 
    
         
             
               - Catch-all routes that handle unknown paths don't pollute the data
         
     | 
| 
       117 
     | 
    
         
            -
               - Only legitimate application  
     | 
| 
       118 
     | 
    
         
            -
            3. **Request Tracking**: Each valid HTTP request is analyzed to extract  
     | 
| 
      
 119 
     | 
    
         
            +
               - Only legitimate application controller actions are analyzed
         
     | 
| 
      
 120 
     | 
    
         
            +
            3. **Request Tracking**: Each valid HTTP request is analyzed to extract controller and action information
         
     | 
| 
       119 
121 
     | 
    
         
             
            4. **Redis Storage**: Usage data is stored in Redis with the following structure:
         
     | 
| 
       120 
     | 
    
         
            -
               -  
     | 
| 
      
 122 
     | 
    
         
            +
               - Controller name and action name
         
     | 
| 
       121 
123 
     | 
    
         
             
               - Access count within the timeframe
         
     | 
| 
       122 
124 
     | 
    
         
             
               - Last access timestamp
         
     | 
| 
       123 
125 
     | 
    
         
             
            5. **Data Expiration**: Redis keys automatically expire after the configured timeframe plus a buffer period
         
     | 
| 
         @@ -132,14 +134,36 @@ The middleware uses Rails' routing system to determine if a route is valid: 
     | 
|
| 
       132 
134 
     | 
    
         | 
| 
       133 
135 
     | 
    
         
             
            This approach ensures that only routes you've intentionally defined are included in the usage analysis.
         
     | 
| 
       134 
136 
     | 
    
         | 
| 
      
 137 
     | 
    
         
            +
            ## Controller Action Tracking
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
            The gem tracks usage by controller and action rather than by specific URL paths. This provides more meaningful insights into which parts of your application are being used:
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
            - **Route Definition**: `resources :users` in `routes.rb`
         
     | 
| 
      
 142 
     | 
    
         
            +
            - **Actual Requests**: `GET /users/123`, `GET /users/456`, `POST /users/789/update`
         
     | 
| 
      
 143 
     | 
    
         
            +
            - **Tracked As**: Separate entries for `users#show` and `users#update` actions
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
            This means that accessing different user IDs (e.g., `/users/123`, `/users/456`, `/users/789`) will all be counted under the same `users#show` action, giving you a clear picture of which controller actions are being utilized.
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
            **Example Output:**
         
     | 
| 
      
 148 
     | 
    
         
            +
            ```
         
     | 
| 
      
 149 
     | 
    
         
            +
            COUNT    CONTROLLER#ACTION       METHOD    LAST ACCESSED
         
     | 
| 
      
 150 
     | 
    
         
            +
            --------------------------------------------------------------
         
     | 
| 
      
 151 
     | 
    
         
            +
            15       users#show              GET       2025-06-18 14:30
         
     | 
| 
      
 152 
     | 
    
         
            +
            8        users#update            PATCH     2025-06-18 12:15
         
     | 
| 
      
 153 
     | 
    
         
            +
            23       posts#show              GET       2025-06-17 09:45
         
     | 
| 
      
 154 
     | 
    
         
            +
            ```
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
            This grouping provides much more meaningful insights into which parts of your application are being used.
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
       135 
158 
     | 
    
         
             
            ## Data Structure
         
     | 
| 
       136 
159 
     | 
    
         | 
| 
       137 
     | 
    
         
            -
            For each tracked  
     | 
| 
      
 160 
     | 
    
         
            +
            For each tracked controller action, the following data is stored in Redis:
         
     | 
| 
       138 
161 
     | 
    
         | 
| 
       139 
162 
     | 
    
         
             
            ```ruby
         
     | 
| 
       140 
163 
     | 
    
         
             
            {
         
     | 
| 
       141 
     | 
    
         
            -
               
     | 
| 
       142 
     | 
    
         
            -
               
     | 
| 
      
 164 
     | 
    
         
            +
              controller: "users",           # Controller name
         
     | 
| 
      
 165 
     | 
    
         
            +
              action: "show",                # Action name
         
     | 
| 
      
 166 
     | 
    
         
            +
              method: "GET",                 # HTTP method (for reference)
         
     | 
| 
       143 
167 
     | 
    
         
             
              count: 15,                     # Number of accesses
         
     | 
| 
       144 
168 
     | 
    
         
             
              last_accessed: 1718721600      # Unix timestamp
         
     | 
| 
       145 
169 
     | 
    
         
             
            }
         
     | 
| 
         @@ -38,7 +38,7 @@ module Routes 
     | 
|
| 
       38 
38 
     | 
    
         | 
| 
       39 
39 
     | 
    
         
             
                    return unless route_info
         
     | 
| 
       40 
40 
     | 
    
         | 
| 
       41 
     | 
    
         
            -
                    redis_key = build_redis_key(route_info[: 
     | 
| 
      
 41 
     | 
    
         
            +
                    redis_key = build_redis_key(route_info[:controller], route_info[:action])
         
     | 
| 
       42 
42 
     | 
    
         
             
                    current_time = Time.current
         
     | 
| 
       43 
43 
     | 
    
         | 
| 
       44 
44 
     | 
    
         
             
                    configuration.redis_client.multi do |redis|
         
     | 
| 
         @@ -48,8 +48,9 @@ module Routes 
     | 
|
| 
       48 
48 
     | 
    
         
             
                      # Update last accessed timestamp
         
     | 
| 
       49 
49 
     | 
    
         
             
                      redis.hset(redis_key, "last_accessed", current_time.to_i)
         
     | 
| 
       50 
50 
     | 
    
         | 
| 
       51 
     | 
    
         
            -
                      # Set  
     | 
| 
       52 
     | 
    
         
            -
                      redis.hset(redis_key, " 
     | 
| 
      
 51 
     | 
    
         
            +
                      # Set controller#action and method info (in case it's the first time)
         
     | 
| 
      
 52 
     | 
    
         
            +
                      redis.hset(redis_key, "controller", route_info[:controller])
         
     | 
| 
      
 53 
     | 
    
         
            +
                      redis.hset(redis_key, "action", route_info[:action])
         
     | 
| 
       53 
54 
     | 
    
         
             
                      redis.hset(redis_key, "method", route_info[:method])
         
     | 
| 
       54 
55 
     | 
    
         | 
| 
       55 
56 
     | 
    
         
             
                      # Set expiration based on timeframe (add some buffer)
         
     | 
| 
         @@ -92,15 +93,12 @@ module Routes 
     | 
|
| 
       92 
93 
     | 
    
         
             
                      controller = env["action_controller.instance"]
         
     | 
| 
       93 
94 
     | 
    
         
             
                      action = controller.action_name
         
     | 
| 
       94 
95 
     | 
    
         
             
                      controller_name = controller.controller_name
         
     | 
| 
       95 
     | 
    
         
            -
             
     | 
| 
       96 
     | 
    
         
            -
                      # Build route pattern from request path, removing query parameters
         
     | 
| 
       97 
     | 
    
         
            -
                      route_path = request.path_info
         
     | 
| 
      
 96 
     | 
    
         
            +
                      method = request.request_method.upcase
         
     | 
| 
       98 
97 
     | 
    
         | 
| 
       99 
98 
     | 
    
         
             
                      {
         
     | 
| 
       100 
     | 
    
         
            -
                        route: route_path,
         
     | 
| 
       101 
     | 
    
         
            -
                        method: request.request_method.upcase,
         
     | 
| 
       102 
99 
     | 
    
         
             
                        controller: controller_name,
         
     | 
| 
       103 
     | 
    
         
            -
                        action: action
         
     | 
| 
      
 100 
     | 
    
         
            +
                        action: action,
         
     | 
| 
      
 101 
     | 
    
         
            +
                        method: method
         
     | 
| 
       104 
102 
     | 
    
         
             
                      }
         
     | 
| 
       105 
103 
     | 
    
         
             
                    end
         
     | 
| 
       106 
104 
     | 
    
         
             
                  rescue => e
         
     | 
| 
         @@ -108,8 +106,8 @@ module Routes 
     | 
|
| 
       108 
106 
     | 
    
         
             
                    nil
         
     | 
| 
       109 
107 
     | 
    
         
             
                  end
         
     | 
| 
       110 
108 
     | 
    
         | 
| 
       111 
     | 
    
         
            -
                  def build_redis_key( 
     | 
| 
       112 
     | 
    
         
            -
                    "#{configuration.redis_key_prefix}:#{ 
     | 
| 
      
 109 
     | 
    
         
            +
                  def build_redis_key(controller, action)
         
     | 
| 
      
 110 
     | 
    
         
            +
                    "#{configuration.redis_key_prefix}:#{controller}##{action}"
         
     | 
| 
       113 
111 
     | 
    
         
             
                  end
         
     | 
| 
       114 
112 
     | 
    
         | 
| 
       115 
113 
     | 
    
         
             
                  def configuration
         
     | 
| 
         @@ -9,7 +9,7 @@ module Routes 
     | 
|
| 
       9 
9 
     | 
    
         
             
                  def get_usage_stats
         
     | 
| 
       10 
10 
     | 
    
         
             
                    cutoff_time = @configuration.timeframe.days.ago.to_i
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
                    # Get all  
     | 
| 
      
 12 
     | 
    
         
            +
                    # Get all controller#action keys
         
     | 
| 
       13 
13 
     | 
    
         
             
                    pattern = "#{@configuration.redis_key_prefix}:*"
         
     | 
| 
       14 
14 
     | 
    
         
             
                    keys = @redis.keys(pattern)
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
         @@ -24,7 +24,8 @@ module Routes 
     | 
|
| 
       24 
24 
     | 
    
         
             
                      next if last_accessed && last_accessed < cutoff_time
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
26 
     | 
    
         
             
                      usage_stats << {
         
     | 
| 
       27 
     | 
    
         
            -
                         
     | 
| 
      
 27 
     | 
    
         
            +
                        controller: route_data["controller"],
         
     | 
| 
      
 28 
     | 
    
         
            +
                        action: route_data["action"],
         
     | 
| 
       28 
29 
     | 
    
         
             
                        method: route_data["method"],
         
     | 
| 
       29 
30 
     | 
    
         
             
                        count: route_data["count"]&.to_i || 0,
         
     | 
| 
       30 
31 
     | 
    
         
             
                        last_accessed: last_accessed ? Time.at(last_accessed) : nil
         
     | 
| 
         @@ -35,54 +36,59 @@ module Routes 
     | 
|
| 
       35 
36 
     | 
    
         
             
                    usage_stats.sort_by { |stat| -stat[:count] }
         
     | 
| 
       36 
37 
     | 
    
         
             
                  end
         
     | 
| 
       37 
38 
     | 
    
         | 
| 
       38 
     | 
    
         
            -
                  def  
     | 
| 
      
 39 
     | 
    
         
            +
                  def get_all_defined_actions
         
     | 
| 
       39 
40 
     | 
    
         
             
                    return [] unless defined?(Rails) && Rails.application
         
     | 
| 
       40 
41 
     | 
    
         | 
| 
       41 
     | 
    
         
            -
                     
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
      
 42 
     | 
    
         
            +
                    actions = []
         
     | 
| 
      
 43 
     | 
    
         
            +
                    Rails.application.routes.routes.each do |route|
         
     | 
| 
      
 44 
     | 
    
         
            +
                      next unless route.defaults[:controller] && route.defaults[:action]
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                      actions << {
         
     | 
| 
       45 
47 
     | 
    
         
             
                        controller: route.defaults[:controller],
         
     | 
| 
       46 
48 
     | 
    
         
             
                        action: route.defaults[:action],
         
     | 
| 
      
 49 
     | 
    
         
            +
                        method: route.verb,
         
     | 
| 
      
 50 
     | 
    
         
            +
                        route: route.path.spec.to_s.gsub(/\(\.:format\)$/, ""),
         
     | 
| 
       47 
51 
     | 
    
         
             
                        name: route.name
         
     | 
| 
       48 
52 
     | 
    
         
             
                      }
         
     | 
| 
       49 
     | 
    
         
            -
                    end 
     | 
| 
      
 53 
     | 
    
         
            +
                    end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                    # Remove duplicates based on controller#action (not method-specific)
         
     | 
| 
      
 56 
     | 
    
         
            +
                    actions.uniq { |a| "#{a[:controller]}##{a[:action]}" }
         
     | 
| 
       50 
57 
     | 
    
         
             
                  end
         
     | 
| 
       51 
58 
     | 
    
         | 
| 
       52 
     | 
    
         
            -
                  def  
     | 
| 
       53 
     | 
    
         
            -
                     
     | 
| 
       54 
     | 
    
         
            -
                     
     | 
| 
      
 59 
     | 
    
         
            +
                  def merge_with_defined_actions(usage_stats)
         
     | 
| 
      
 60 
     | 
    
         
            +
                    defined_actions = get_all_defined_actions
         
     | 
| 
      
 61 
     | 
    
         
            +
                    usage_by_action = usage_stats.index_by { |stat| "#{stat[:controller]}##{stat[:action]}" }
         
     | 
| 
       55 
62 
     | 
    
         | 
| 
       56 
     | 
    
         
            -
                     
     | 
| 
      
 63 
     | 
    
         
            +
                    merged_actions = []
         
     | 
| 
       57 
64 
     | 
    
         | 
| 
       58 
     | 
    
         
            -
                     
     | 
| 
       59 
     | 
    
         
            -
                       
     | 
| 
       60 
     | 
    
         
            -
                      usage_stat =  
     | 
| 
      
 65 
     | 
    
         
            +
                    defined_actions.each do |defined_action|
         
     | 
| 
      
 66 
     | 
    
         
            +
                      action_key = "#{defined_action[:controller]}##{defined_action[:action]}"
         
     | 
| 
      
 67 
     | 
    
         
            +
                      usage_stat = usage_by_action[action_key]
         
     | 
| 
       61 
68 
     | 
    
         | 
| 
       62 
69 
     | 
    
         
             
                      if usage_stat
         
     | 
| 
       63 
     | 
    
         
            -
                         
     | 
| 
      
 70 
     | 
    
         
            +
                        merged_actions << defined_action.merge(usage_stat)
         
     | 
| 
       64 
71 
     | 
    
         
             
                      else
         
     | 
| 
       65 
     | 
    
         
            -
                         
     | 
| 
      
 72 
     | 
    
         
            +
                        merged_actions << defined_action.merge(
         
     | 
| 
       66 
73 
     | 
    
         
             
                          count: 0,
         
     | 
| 
       67 
74 
     | 
    
         
             
                          last_accessed: nil
         
     | 
| 
       68 
75 
     | 
    
         
             
                        )
         
     | 
| 
       69 
76 
     | 
    
         
             
                      end
         
     | 
| 
       70 
77 
     | 
    
         
             
                    end
         
     | 
| 
       71 
78 
     | 
    
         | 
| 
       72 
     | 
    
         
            -
                    # Add any tracked  
     | 
| 
      
 79 
     | 
    
         
            +
                    # Add any tracked actions that aren't in the defined actions (in case of dynamic actions)
         
     | 
| 
       73 
80 
     | 
    
         
             
                    usage_stats.each do |usage_stat|
         
     | 
| 
       74 
     | 
    
         
            -
                       
     | 
| 
       75 
     | 
    
         
            -
                      unless  
     | 
| 
       76 
     | 
    
         
            -
                         
     | 
| 
       77 
     | 
    
         
            -
                           
     | 
| 
       78 
     | 
    
         
            -
                          action: nil,
         
     | 
| 
      
 81 
     | 
    
         
            +
                      action_key = "#{usage_stat[:controller]}##{usage_stat[:action]}"
         
     | 
| 
      
 82 
     | 
    
         
            +
                      unless defined_actions.any? { |da| "#{da[:controller]}##{da[:action]}" == action_key }
         
     | 
| 
      
 83 
     | 
    
         
            +
                        merged_actions << usage_stat.merge(
         
     | 
| 
      
 84 
     | 
    
         
            +
                          route: nil,
         
     | 
| 
       79 
85 
     | 
    
         
             
                          name: nil
         
     | 
| 
       80 
86 
     | 
    
         
             
                        )
         
     | 
| 
       81 
87 
     | 
    
         
             
                      end
         
     | 
| 
       82 
88 
     | 
    
         
             
                    end
         
     | 
| 
       83 
89 
     | 
    
         | 
| 
       84 
     | 
    
         
            -
                    # Sort by count (descending), then by  
     | 
| 
       85 
     | 
    
         
            -
                     
     | 
| 
      
 90 
     | 
    
         
            +
                    # Sort by count (descending), then by controller#action name
         
     | 
| 
      
 91 
     | 
    
         
            +
                    merged_actions.sort_by { |action| [ -action[:count], "#{action[:controller]}##{action[:action]}" ] }
         
     | 
| 
       86 
92 
     | 
    
         
             
                  end
         
     | 
| 
       87 
93 
     | 
    
         
             
                end
         
     | 
| 
       88 
94 
     | 
    
         
             
              end
         
     | 
| 
         @@ -1,60 +1,59 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            namespace :routes do
         
     | 
| 
       2 
2 
     | 
    
         
             
              namespace :analyzer do
         
     | 
| 
       3 
     | 
    
         
            -
                desc "Show  
     | 
| 
      
 3 
     | 
    
         
            +
                desc "Show controller action usage statistics"
         
     | 
| 
       4 
4 
     | 
    
         
             
                task usage: :environment do
         
     | 
| 
       5 
5 
     | 
    
         
             
                  begin
         
     | 
| 
       6 
6 
     | 
    
         
             
                    config = Routes::Analyzer.configuration
         
     | 
| 
       7 
7 
     | 
    
         
             
                    tracker = Routes::Analyzer::RouteUsageTracker.new(config)
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
                    puts " 
     | 
| 
      
 9 
     | 
    
         
            +
                    puts "Controller Action Usage Analysis (#{config.timeframe} days)"
         
     | 
| 
       10 
10 
     | 
    
         
             
                    puts "=" * 80
         
     | 
| 
       11 
11 
     | 
    
         
             
                    puts
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
                    if config.valid?
         
     | 
| 
       14 
14 
     | 
    
         
             
                      usage_stats = tracker.get_usage_stats
         
     | 
| 
       15 
     | 
    
         
            -
                       
     | 
| 
      
 15 
     | 
    
         
            +
                      merged_actions = tracker.merge_with_defined_actions(usage_stats)
         
     | 
| 
       16 
16 
     | 
    
         
             
                    else
         
     | 
| 
       17 
     | 
    
         
            -
                      puts "Warning: Redis not configured. Showing defined  
     | 
| 
      
 17 
     | 
    
         
            +
                      puts "Warning: Redis not configured. Showing defined actions only."
         
     | 
| 
       18 
18 
     | 
    
         
             
                      puts
         
     | 
| 
       19 
     | 
    
         
            -
                       
     | 
| 
       20 
     | 
    
         
            -
                         
     | 
| 
      
 19 
     | 
    
         
            +
                      merged_actions = tracker.get_all_defined_actions.map do |action|
         
     | 
| 
      
 20 
     | 
    
         
            +
                        action.merge(count: 0, last_accessed: nil)
         
     | 
| 
       21 
21 
     | 
    
         
             
                      end
         
     | 
| 
       22 
22 
     | 
    
         
             
                    end
         
     | 
| 
       23 
23 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
                    if  
     | 
| 
       25 
     | 
    
         
            -
                      puts "No  
     | 
| 
      
 24 
     | 
    
         
            +
                    if merged_actions.empty?
         
     | 
| 
      
 25 
     | 
    
         
            +
                      puts "No controller actions found."
         
     | 
| 
       26 
26 
     | 
    
         
             
                      next
         
     | 
| 
       27 
27 
     | 
    
         
             
                    end
         
     | 
| 
       28 
28 
     | 
    
         | 
| 
       29 
29 
     | 
    
         
             
                    # Print header
         
     | 
| 
       30 
     | 
    
         
            -
                    printf "%-8s %-40s %-15s  
     | 
| 
      
 30 
     | 
    
         
            +
                    printf "%-8s %-40s %-15s %s\n", "COUNT", "CONTROLLER#ACTION", "METHOD", "LAST ACCESSED"
         
     | 
| 
       31 
31 
     | 
    
         
             
                    puts "-" * 80
         
     | 
| 
       32 
32 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
                     
     | 
| 
       34 
     | 
    
         
            -
                      controller_action = if  
     | 
| 
       35 
     | 
    
         
            -
                        "#{ 
     | 
| 
      
 33 
     | 
    
         
            +
                    merged_actions.each do |action|
         
     | 
| 
      
 34 
     | 
    
         
            +
                      controller_action = if action[:controller] && action[:action]
         
     | 
| 
      
 35 
     | 
    
         
            +
                        "#{action[:controller]}##{action[:action]}"
         
     | 
| 
       36 
36 
     | 
    
         
             
                      else
         
     | 
| 
       37 
37 
     | 
    
         
             
                        "N/A"
         
     | 
| 
       38 
38 
     | 
    
         
             
                      end
         
     | 
| 
       39 
39 
     | 
    
         | 
| 
       40 
     | 
    
         
            -
                      last_accessed = if  
     | 
| 
       41 
     | 
    
         
            -
                         
     | 
| 
      
 40 
     | 
    
         
            +
                      last_accessed = if action[:last_accessed]
         
     | 
| 
      
 41 
     | 
    
         
            +
                        action[:last_accessed].strftime("%Y-%m-%d %H:%M")
         
     | 
| 
       42 
42 
     | 
    
         
             
                      else
         
     | 
| 
       43 
43 
     | 
    
         
             
                        "Never"
         
     | 
| 
       44 
44 
     | 
    
         
             
                      end
         
     | 
| 
       45 
45 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
                      printf "%-8d %-40s %-15s  
     | 
| 
       47 
     | 
    
         
            -
                              
     | 
| 
       48 
     | 
    
         
            -
                              
     | 
| 
       49 
     | 
    
         
            -
                              
     | 
| 
       50 
     | 
    
         
            -
                             controller_action[0, 20],
         
     | 
| 
      
 46 
     | 
    
         
            +
                      printf "%-8d %-40s %-15s %s\n",
         
     | 
| 
      
 47 
     | 
    
         
            +
                             action[:count],
         
     | 
| 
      
 48 
     | 
    
         
            +
                             controller_action[0, 40],
         
     | 
| 
      
 49 
     | 
    
         
            +
                             action[:method],
         
     | 
| 
       51 
50 
     | 
    
         
             
                             last_accessed
         
     | 
| 
       52 
51 
     | 
    
         
             
                    end
         
     | 
| 
       53 
52 
     | 
    
         | 
| 
       54 
53 
     | 
    
         
             
                    puts
         
     | 
| 
       55 
     | 
    
         
            -
                    puts "Total  
     | 
| 
       56 
     | 
    
         
            -
                    puts "Used  
     | 
| 
       57 
     | 
    
         
            -
                    puts "Unused  
     | 
| 
      
 54 
     | 
    
         
            +
                    puts "Total actions: #{merged_actions.count}"
         
     | 
| 
      
 55 
     | 
    
         
            +
                    puts "Used actions: #{merged_actions.count { |a| a[:count] > 0 }}"
         
     | 
| 
      
 56 
     | 
    
         
            +
                    puts "Unused actions: #{merged_actions.count { |a| a[:count] == 0 }}"
         
     | 
| 
       58 
57 
     | 
    
         | 
| 
       59 
58 
     | 
    
         
             
                  rescue => e
         
     | 
| 
       60 
59 
     | 
    
         
             
                    puts "Error: #{e.message}"
         
     | 
| 
         @@ -69,7 +68,7 @@ namespace :routes do 
     | 
|
| 
       69 
68 
     | 
    
         
             
                  end
         
     | 
| 
       70 
69 
     | 
    
         
             
                end
         
     | 
| 
       71 
70 
     | 
    
         | 
| 
       72 
     | 
    
         
            -
                desc "Clear all  
     | 
| 
      
 71 
     | 
    
         
            +
                desc "Clear all controller action usage data"
         
     | 
| 
       73 
72 
     | 
    
         
             
                task clear: :environment do
         
     | 
| 
       74 
73 
     | 
    
         
             
                  begin
         
     | 
| 
       75 
74 
     | 
    
         
             
                    config = Routes::Analyzer.configuration
         
     | 
| 
         @@ -79,9 +78,9 @@ namespace :routes do 
     | 
|
| 
       79 
78 
     | 
    
         | 
| 
       80 
79 
     | 
    
         
             
                    if keys.any?
         
     | 
| 
       81 
80 
     | 
    
         
             
                      redis.del(*keys)
         
     | 
| 
       82 
     | 
    
         
            -
                      puts "Cleared #{keys.count}  
     | 
| 
      
 81 
     | 
    
         
            +
                      puts "Cleared #{keys.count} controller action usage records."
         
     | 
| 
       83 
82 
     | 
    
         
             
                    else
         
     | 
| 
       84 
     | 
    
         
            -
                      puts "No  
     | 
| 
      
 83 
     | 
    
         
            +
                      puts "No controller action usage data found to clear."
         
     | 
| 
       85 
84 
     | 
    
         
             
                    end
         
     | 
| 
       86 
85 
     | 
    
         | 
| 
       87 
86 
     | 
    
         
             
                  rescue => e
         
     |