rails_visualizer 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 92930541e9b74dde2cddec0f9314b9204c05fad9151f2e4aac4b7415a4246f14
4
+ data.tar.gz: 7bb8078d83854514a4709a1b63446d3f6a951409f100e7310b8e13613004534f
5
+ SHA512:
6
+ metadata.gz: ccd2f5078b94d8870991ea38d5e2ba646d49beee4b258b8693c628c5ea55678b56e76eaa723dcda881eea20b7d32023a550be6dc52a897b2092e79d03930387c
7
+ data.tar.gz: 86d1a1b4ff05263750292e56f15d7709b64a8e15bde8e47c577cd084ab1370304114672c4df8a37f88d715b71b9b3c222c5ac0ddbe335749807dc42cbee6cdbf
data/CHANGELOG.md ADDED
@@ -0,0 +1,36 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-05-18
11
+
12
+ ### Added
13
+
14
+ - `RailsVisualizer::Introspector` — orchestrates parallel inspection of all app layers using threads for I/O-bound work and fork-based workers for CPU-bound model inspection on large apps
15
+ - `RailsVisualizer::Schema::ModelInspector` — inspects ActiveRecord models for columns, associations, validations, enums, scopes, and lifecycle callbacks with shared file and method-location caches for performance
16
+ - `RailsVisualizer::Schema::Cache` — bulk-loads column and index metadata with PostgreSQL-optimised parallel SQL queries and a per-adapter fallback
17
+ - `RailsVisualizer::Schema::IndexInspector` — reads database indexes per table
18
+ - `RailsVisualizer::RoutesInspector` — collects all application routes with verb, path, controller, action, namespace, internal flag, and constraint data
19
+ - `RailsVisualizer::ControllersInspector` — collects ActionController classes with routable actions, public helpers, and before/after/around callbacks (including `only:`, `except:`, `if:`, `unless:` restrictions and inherited-from tracking)
20
+ - `RailsVisualizer::JobsInspector` — collects ActiveJob and Sidekiq worker classes with queue, priority, retry, and discard configuration
21
+ - `RailsVisualizer::MailersInspector` — collects ActionMailer classes with email action methods and default sender
22
+ - `RailsVisualizer::MigrationsInspector` — reads migration files and the `schema_migrations` table to report applied/pending status and summary counts
23
+ - `RailsVisualizer::GemsInspector` — reads Bundler gem dependencies with version, environment groups, source (RubyGems / GitHub / GitLab / path), and `require:` configuration
24
+ - `RailsVisualizer::Serializer` — converts introspection data to camelCase JSON with memoised key conversion
25
+ - `RailsVisualizer::Renderer` — injects JSON into a pre-built, self-contained React HTML template via a placeholder script tag
26
+ - `RailsVisualizer::Configuration` — configurable options: `excluded_models`, `output_path`, `open_browser`, `theme`, `verbose`
27
+ - `rails_visualizer` Rake task — single command: introspect → serialize → render → open browser
28
+ - 8-tab interactive HTML dashboard (Overview, Gems, Routes, Controllers, Models, Migrations, Jobs, Mailers) built with React 18, Tailwind CSS, and React Flow
29
+ - ER diagram canvas with automatic Dagre layout, zoom/pan, minimap, and a model detail sidebar
30
+ - Search bars, filter chips, and item counts across all tabs
31
+ - Health checks on the Overview tab with cross-tab navigation
32
+ - Light / dark / system theme support with localStorage persistence
33
+ - `IssuesOnly` filter to focus on models without validations, pending migrations, mailers without a default sender, and unrouted controller actions
34
+
35
+ [Unreleased]: https://github.com/rajkamallashkari/rails_visualizer/compare/v0.1.0...HEAD
36
+ [0.1.0]: https://github.com/rajkamallashkari/rails_visualizer/releases/tag/v0.1.0
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Raj Kamal Lashkari
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,509 @@
1
+ # RailsVisualizer
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/rails_visualizer.svg)](https://badge.fury.io/rb/rails_visualizer)
4
+ [![Ruby](https://img.shields.io/badge/ruby-%3E%3D%203.0-CC342D)](https://www.ruby-lang.org)
5
+ [![Rails](https://img.shields.io/badge/rails-%3E%3D%207.0-D30001)](https://rubyonrails.org)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE.txt)
7
+
8
+ > One command. A full interactive dashboard for your Rails app.
9
+
10
+ RailsVisualizer introspects your Rails application and generates a **self-contained interactive HTML dashboard** — no server, no config, no Node.js required. Run one Rake task and explore your models, associations, routes, controllers, jobs, mailers, migrations, and gems through a polished 8-tab UI with search, filters, an ER diagram canvas, and built-in health checks.
11
+
12
+ The generated file contains **all JavaScript and CSS inline** — it works offline, loads instantly, and can be shared as a single file with zero external dependencies.
13
+
14
+ ---
15
+
16
+ ## Table of Contents
17
+
18
+ - [Installation](#installation)
19
+ - [Quick Start](#quick-start)
20
+ - [Dashboard Tabs](#dashboard-tabs)
21
+ - [Overview](#overview)
22
+ - [Gems](#gems)
23
+ - [Routes](#routes)
24
+ - [Controllers](#controllers)
25
+ - [Models](#models)
26
+ - [Migrations](#migrations)
27
+ - [Jobs](#jobs)
28
+ - [Mailers](#mailers)
29
+ - [Configuration](#configuration)
30
+ - [Health Checks](#health-checks)
31
+ - [How It Works](#how-it-works)
32
+ - [Performance](#performance)
33
+ - [Compatibility](#compatibility)
34
+ - [FAQ](#faq)
35
+ - [Development](#development)
36
+ - [Contributing](#contributing)
37
+ - [License](#license)
38
+
39
+ ---
40
+
41
+ ## Installation
42
+
43
+ Add `rails_visualizer` to your `Gemfile`. Since it only introspects the app and is never needed in production, place it in the `development` group:
44
+
45
+ ```ruby
46
+ group :development do
47
+ gem 'rails_visualizer'
48
+ end
49
+ ```
50
+
51
+ Then run:
52
+
53
+ ```bash
54
+ bundle install
55
+ ```
56
+
57
+ That's it — no generators, no migrations, no configuration files needed.
58
+
59
+ ## Quick Start
60
+
61
+ ```bash
62
+ bundle exec rake rails_visualizer
63
+ ```
64
+
65
+ This single command will:
66
+
67
+ 1. Eager-load your Rails application.
68
+ 2. Introspect models, routes, controllers, jobs, mailers, migrations, and gems.
69
+ 3. Generate a self-contained HTML file at `tmp/rails_visualizer/index.html`.
70
+ 4. Open it in your default browser automatically.
71
+
72
+ Example output:
73
+
74
+ ```
75
+ RailsVisualizer: Introspecting app...
76
+ ✓ 47 models
77
+ ✓ 128 routes
78
+ ✓ 12 jobs
79
+ ⚠ 31 controllers (3 actions without route)
80
+ ⚠ 64 migrations (2 pending migrations)
81
+ ✓ 4 mailers
82
+ RailsVisualizer: Rendering...
83
+ RailsVisualizer: Done → tmp/rails_visualizer/index.html
84
+ ```
85
+
86
+ The generated HTML file is completely standalone — email it, commit it, drop it in Slack, or open it on any machine. No server required.
87
+
88
+ ## Dashboard Tabs
89
+
90
+ ### Overview
91
+
92
+ The landing tab gives you a bird's-eye view of your entire application:
93
+
94
+ - **App header** — displays your app name, page title (extracted from the layout), favicon (auto-detected from `public/`), and version badges for Rails, Ruby, your database (PostgreSQL, MySQL, or SQLite), and background job processor (Sidekiq, GoodJob, Solid Queue, etc.).
95
+ - **Stats grid** — clickable cards for each area (Gems, Routes, Controllers, Models, Migrations, Jobs, Mailers) showing counts and sub-stats like HTTP verb breakdown, column counts, queue counts, and more. Warning badges appear on cards that have issues.
96
+ - **Health checks** — a prioritized checklist that surfaces problems across your codebase, with "Go to" links that navigate directly to the relevant tab. See [Health Checks](#health-checks) for the full list.
97
+
98
+ ### Gems
99
+
100
+ Displays every dependency from your `Gemfile`:
101
+
102
+ - **Name**, **version**, and **version constraint** (e.g. `~> 7.0`).
103
+ - **Summary** pulled from the gem's metadata.
104
+ - **Environment groups** — color-coded chips for Common, Development, Test, and Production.
105
+ - **Source tags** — shows non-standard sources like `github: owner/repo`, `branch: main`, `path: engines/erp`, or `require: false`.
106
+ - **Homepage link** — external link icon for each gem.
107
+ - **Filters** — filter by environment group (Common, Development, Test, Production).
108
+ - **Search** — search across gem name, summary, and version.
109
+
110
+ ### Routes
111
+
112
+ Shows every route defined in `config/routes.rb`:
113
+
114
+ - **HTTP verb** — color-coded badge (GET green, POST blue, PATCH/PUT amber, DELETE red).
115
+ - **Path** — with `:param` segments highlighted and `(format)` segments dimmed.
116
+ - **Controller#action** — linked pair showing the target.
117
+ - **Route name** — the named helper (e.g. `edit_user`).
118
+ - **Constraints** — any route constraints displayed as chips.
119
+ - **Orphaned route detection** — routes pointing to non-existent controllers are flagged with a red "Orphaned" badge.
120
+ - **Filters** — toggle by HTTP verb (GET, POST, PATCH, PUT, DELETE) and an "Issues only" toggle to show only orphaned routes.
121
+ - **Copy** and **Open in editor** buttons for path and controller file.
122
+
123
+ ### Controllers
124
+
125
+ Namespace-grouped tree view of all your ActionController classes:
126
+
127
+ - **Actions** — each public action is displayed as a pill, with RESTful actions (index, show, new, create, edit, update, destroy) getting a CRUD badge and tooltip description.
128
+ - **Unrouted action warnings** — actions without a matching route get an amber "No route" badge. If the action is a template method routed via child controllers, it shows "Routed via ChildController" instead.
129
+ - **Callbacks** — `before_action`, `after_action`, and `around_action` with full metadata:
130
+ - `only:` and `except:` restrictions
131
+ - `if:` and `unless:` conditions
132
+ - Inherited callback tracking (shows which parent class defined it)
133
+ - Custom Proc condition indicator
134
+ - **Public helpers** — non-routable public methods (ending in `?` or `=`) that might need visibility changes.
135
+ - **Superclass** shown for each controller.
136
+ - **Issues only** toggle to filter down to controllers with unrouted actions.
137
+
138
+ ### Models
139
+
140
+ The richest tab, with two view modes:
141
+
142
+ #### List View
143
+
144
+ A namespace-grouped tree of all ActiveRecord models. Click any model to open a detail sidebar showing:
145
+
146
+ - **Columns** — name, type, nullability, default value, index info, and enum values.
147
+ - **Associations** — `has_many`, `belongs_to`, `has_one`, `has_many :through`, and `has_and_belongs_to_many` with class name, foreign key, `dependent:`, `as:` (polymorphic), and `through:` details.
148
+ - **Validations** — each validator with its kind, attributes, options, and validator class.
149
+ - **Enums** — enum name and all possible values.
150
+ - **Scopes** — named scopes defined in the model file.
151
+ - **Callbacks** — lifecycle callbacks (`before_save`, `after_create`, `around_destroy`, etc.) with the owning module/concern if inherited.
152
+
153
+ #### Canvas View (ER Diagram)
154
+
155
+ An interactive **React Flow** canvas that renders your schema as an entity-relationship diagram:
156
+
157
+ - **Model nodes** — cards showing the model name and its columns with types and constraints.
158
+ - **Association edges** — labeled, color-coded lines between related models.
159
+ - **Automatic layout** — powered by Dagre for clean graph arrangement.
160
+ - **Zoom, pan, and minimap** — navigate large schemas with ease.
161
+ - **Click-to-select** — click any model node to open the detail sidebar.
162
+
163
+ Both views support:
164
+
165
+ - **Search** — filter models by name or table name.
166
+ - **Issues only toggle** — filter to models without any validations.
167
+
168
+ ### Migrations
169
+
170
+ Lists every migration file in `db/migrate/`:
171
+
172
+ - **Status** — green "Applied" badge or red "Pending" badge.
173
+ - **Human-readable name** — e.g. "Create Users" from `20240101_create_users.rb`.
174
+ - **Version timestamp** — parsed into a readable date.
175
+ - **Current version** indicator on the latest applied migration.
176
+ - **Filter** — by status (Applied, Pending) and search by name or version.
177
+ - **Open in editor** button for each migration file.
178
+
179
+ ### Jobs
180
+
181
+ Covers both **ActiveJob** classes and **Sidekiq** workers:
182
+
183
+ - **Namespace tree** — jobs grouped by `::` module separators into a collapsible tree.
184
+ - **Queue** — color-coded badge per queue name.
185
+ - **ActiveJob details** — queue name, priority, `retry_on` handlers, and `discard_on` configuration.
186
+ - **Sidekiq details** — queue, retry setting, and uniqueness configuration. Workers with retries disabled get an amber warning.
187
+ - **Adapter info** — shows the configured queue adapter (Sidekiq, GoodJob, Solid Queue, etc.) with a description.
188
+ - **Filter** — by queue name, and an "Issues only" toggle for Sidekiq workers with retries disabled.
189
+
190
+ ### Mailers
191
+
192
+ Namespace tree of all ActionMailer classes:
193
+
194
+ - **Email actions** — each mailer method displayed as a pill.
195
+ - **Inherited actions** — collapsible section showing email methods inherited from parent mailers, grouped by the defining class.
196
+ - **Default from** — the configured `default from:` address. Mailers without one are flagged.
197
+ - **Default reply-to** — if configured.
198
+ - **Layout** — the mailer layout name.
199
+ - **Callbacks** — `before_action`, `after_action`, and `around_action` on the mailer.
200
+ - **Abstract detection** — mailers with no own email methods that serve as base classes are marked as abstract.
201
+ - **Issues only** toggle to filter to mailers without a `default_from`.
202
+
203
+ ## Configuration
204
+
205
+ Create an initializer to customize any defaults. All settings are optional:
206
+
207
+ ```ruby
208
+ # config/initializers/rails_visualizer.rb
209
+ RailsVisualizer.configure do |config|
210
+ # Exclude specific model class names from introspection.
211
+ # Useful for internal/legacy models you don't want in the dashboard.
212
+ config.excluded_models = ['AuditLog', 'InternalSession']
213
+
214
+ # Exclude specific controller class names.
215
+ config.excluded_controllers = ['HealthCheckController', 'Admin::InternalController']
216
+
217
+ # Exclude specific job class names.
218
+ config.excluded_jobs = ['LegacyCleanupJob']
219
+
220
+ # Exclude specific mailer class names.
221
+ config.excluded_mailers = ['InternalNotifier']
222
+
223
+ # Exclude routes whose paths start with these prefixes.
224
+ # Handy for mounted engines like Sidekiq Web or ActiveAdmin.
225
+ config.excluded_route_paths = ['/admin', '/sidekiq']
226
+
227
+ # Directory where the HTML file is written (relative to Rails.root).
228
+ config.output_path = 'tmp/rails_visualizer'
229
+
230
+ # Output filename.
231
+ config.filename = 'index.html'
232
+
233
+ # Automatically open the browser after generation. Set to false for CI or scripts.
234
+ config.open_browser = true
235
+
236
+ # Default color theme for the dashboard. Users can change it in the UI.
237
+ # :light or :dark
238
+ config.theme = :light
239
+
240
+ # Use fork-based parallel workers for model inspection on large apps.
241
+ # Disable if forking causes issues with your database driver or environment.
242
+ config.parallel = true
243
+ end
244
+ ```
245
+
246
+ ### Configuration Options Reference
247
+
248
+ | Option | Type | Default | Description |
249
+ |--------|------|---------|-------------|
250
+ | `excluded_models` | `Array<String>` | `[]` | Model class names to exclude |
251
+ | `excluded_controllers` | `Array<String>` | `[]` | Controller class names to exclude |
252
+ | `excluded_jobs` | `Array<String>` | `[]` | Job class names to exclude |
253
+ | `excluded_mailers` | `Array<String>` | `[]` | Mailer class names to exclude |
254
+ | `excluded_route_paths` | `Array<String>` | `[]` | Route path prefixes to exclude |
255
+ | `output_path` | `String` | `'tmp/rails_visualizer'` | Output directory (relative to `Rails.root`) |
256
+ | `filename` | `String` | `'index.html'` | Output file name |
257
+ | `open_browser` | `Boolean` | `true` | Auto-open browser after generation |
258
+ | `theme` | `Symbol` | `:light` | Default theme (`:light` or `:dark`) |
259
+ | `parallel` | `Boolean` | `true` | Enable fork-based parallel model inspection |
260
+
261
+ ### Disabling Browser Auto-Open
262
+
263
+ If you're running in CI, scripting, or just want the file without opening a browser:
264
+
265
+ ```ruby
266
+ RailsVisualizer.configure do |config|
267
+ config.open_browser = false
268
+ end
269
+ ```
270
+
271
+ ### Excluding Mounted Engine Routes
272
+
273
+ Many apps mount engines like Sidekiq Web, ActiveAdmin, or Letter Opener that add many routes you may not want to visualize:
274
+
275
+ ```ruby
276
+ RailsVisualizer.configure do |config|
277
+ config.excluded_route_paths = ['/admin', '/sidekiq', '/letter_opener']
278
+ end
279
+ ```
280
+
281
+ ## Health Checks
282
+
283
+ The Overview tab runs automated health checks across your application and surfaces issues at a glance. Each check has a severity level:
284
+
285
+ | Check | Severity | Passes when |
286
+ |-------|----------|-------------|
287
+ | **Orphaned routes** | Error | All routes point to a known controller class |
288
+ | **Unrouted actions** | Warning | All public controller actions have a matching route |
289
+ | **Models without validations** | Warning | All models have at least one validation |
290
+ | **Pending migrations** | Error | All migrations have been applied |
291
+ | **Sidekiq retries disabled** | Warning | All Sidekiq workers have retries enabled |
292
+ | **Mailers without default_from** | Warning | All mailers have a `default from:` address |
293
+
294
+ Each failing check has a **"Go to"** button that navigates to the relevant tab where you can see the full details.
295
+
296
+ ## How It Works
297
+
298
+ ```
299
+ Rake task
300
+ └─ Introspector
301
+ ├─ eager_load! (load all classes)
302
+ ├─ 5 parallel Threads (routes, controllers, jobs, mailers, gems)
303
+ ├─ Schema::Cache (bulk DB metadata in 2 SQL queries on PG)
304
+ ├─ MigrationsInspector
305
+ └─ ModelInspector (fork-based workers for 50+ models)
306
+ └─ per-model: columns, associations, validations, enums, scopes, callbacks
307
+ └─ Serializer (Ruby Hash → camelCase JSON)
308
+ └─ Renderer (inject JSON into pre-built React HTML)
309
+ └─ Write tmp/rails_visualizer/index.html
310
+ └─ Open browser
311
+ ```
312
+
313
+ ### Step by Step
314
+
315
+ 1. **Eager-load** — `Rails.application.eager_load!` ensures all classes are defined before introspection begins.
316
+
317
+ 2. **Parallel introspection** — five inspectors run in parallel threads: `RoutesInspector`, `ControllersInspector`, `JobsInspector`, `MailersInspector`, and `GemsInspector`. Since these are I/O-bound (filesystem reads, route table traversal), threads give a meaningful speedup even with the GIL.
318
+
319
+ 3. **Database metadata** — `Schema::Cache` bulk-loads all column and index metadata. On PostgreSQL, this runs **two parallel SQL queries** against `information_schema.columns` and `pg_index` with a SQL-level table filter for maximum speed. Other adapters use a per-table fallback through the ActiveRecord API.
320
+
321
+ 4. **Model inspection** — `Schema::ModelInspector` inspects each model for columns, associations, validations, enums, scopes, and callbacks. On large apps (50+ models), inspection runs in **fork-based parallel workers** (up to 8 processes) for significant speedup on multi-core machines. Results are passed back via `Marshal.dump`/`load` through temp files.
322
+
323
+ 5. **Serialization** — `Serializer` converts the Ruby hash to JSON, recursively transforming all `snake_case` keys to `camelCase` with memoized key conversion.
324
+
325
+ 6. **Rendering** — `Renderer` reads the pre-built React HTML template and injects the JSON via a placeholder `<script>` tag, producing a single self-contained HTML file.
326
+
327
+ 7. **Output** — the file is written to disk and optionally opened in the browser.
328
+
329
+ ### Error Resilience
330
+
331
+ Every inspector follows the same safety pattern:
332
+
333
+ ```ruby
334
+ def call
335
+ # ... introspection logic
336
+ rescue StandardError
337
+ [] # safe default — never crash the host app
338
+ end
339
+ ```
340
+
341
+ Individual model/controller/job failures are caught and skipped. Warnings are printed via `warn "[RailsVisualizer] ..."` but never raise.
342
+
343
+ ## Performance
344
+
345
+ RailsVisualizer is designed to be fast even on large codebases:
346
+
347
+ - **Parallel threads** for I/O-bound inspectors (routes, controllers, jobs, mailers, gems).
348
+ - **Fork-based workers** for CPU-bound model inspection when you have 50+ models (automatically scales up to 8 processes based on CPU count).
349
+ - **Bulk SQL** on PostgreSQL — two queries total for all column and index metadata, instead of per-table queries.
350
+ - **Shared caches** — file content, method source locations, and enum lookups are cached across models to avoid redundant work.
351
+ - **Memoized key conversion** — the Serializer reuses the same ~30 camelCase key transforms across thousands of objects.
352
+
353
+ If you experience issues with fork-based parallelism (e.g. database driver compatibility), disable it:
354
+
355
+ ```ruby
356
+ RailsVisualizer.configure do |config|
357
+ config.parallel = false
358
+ end
359
+ ```
360
+
361
+ ## Compatibility
362
+
363
+ - **Ruby** >= 3.0
364
+ - **Rails** >= 7.0 (tested on 7.0, 7.1, 7.2, 8.0+)
365
+ - **PostgreSQL** — optimized with bulk-loaded parallel SQL queries for maximum speed
366
+ - **MySQL** — full support via per-table ActiveRecord API fallback
367
+ - **SQLite** — full support via per-table ActiveRecord API fallback
368
+ - **Any other ActiveRecord adapter** — per-table fallback with identical output
369
+ - **Zero runtime dependencies** — the gem adds nothing to your production bundle
370
+ - **ActionController::API** — API-only apps are fully supported alongside traditional apps
371
+ - **Sidekiq** — Sidekiq workers are detected alongside ActiveJob classes
372
+
373
+ ## FAQ
374
+
375
+ **Does this affect my production app?**
376
+ No. The gem should be in the `:development` group and is only activated when you explicitly run the Rake task.
377
+
378
+ **Do I need Node.js?**
379
+ No. The frontend is pre-built into a single HTML file and committed to the gem. End users never need Node.js.
380
+
381
+ **Can I share the generated HTML file?**
382
+ Yes. The file is completely self-contained — all JavaScript, CSS, and data are inlined. Drop it in Slack, attach it to a PR, or email it. It works offline on any machine with a browser.
383
+
384
+ **Does it work with API-only Rails apps?**
385
+ Yes. Both `ActionController::Base` and `ActionController::API` controllers are introspected.
386
+
387
+ **What about STI / abstract models?**
388
+ Abstract models are excluded from introspection by default. STI models are included and shown with their own columns and associations.
389
+
390
+ **My app has 500+ models — will it be slow?**
391
+ The gem automatically uses fork-based parallel workers for large apps (50+ models, up to 8 workers). PostgreSQL users benefit from bulk SQL queries. A 500-model app typically generates in under 10 seconds.
392
+
393
+ **Can I customize the output path?**
394
+ Yes. See the [Configuration](#configuration) section. You can change both the directory and filename.
395
+
396
+ **The browser didn't open automatically.**
397
+ Set `config.open_browser = true` (the default) and make sure your system has a default browser configured. On Linux, the `open` command is replaced by `xdg-open` — if that's not working, set `open_browser` to false and open the file manually.
398
+
399
+ **How do I regenerate after code changes?**
400
+ Just run `bundle exec rake rails_visualizer` again. The file is overwritten each time.
401
+
402
+ **Does it detect issues?**
403
+ Yes. The Overview tab includes health checks for orphaned routes, unrouted controller actions, models without validations, pending migrations, Sidekiq workers with retries disabled, and mailers without a `default_from`. See [Health Checks](#health-checks).
404
+
405
+ ## Development
406
+
407
+ Clone the repo and install dependencies:
408
+
409
+ ```bash
410
+ git clone https://github.com/rajkamallashkari/rails_visualizer.git
411
+ cd rails_visualizer
412
+ bundle install
413
+ ```
414
+
415
+ ### Running Tests
416
+
417
+ ```bash
418
+ bundle exec rspec
419
+ ```
420
+
421
+ The test suite boots a minimal dummy Rails app with an in-memory SQLite database, so no external database is needed.
422
+
423
+ ### Running RuboCop
424
+
425
+ ```bash
426
+ bundle exec rubocop
427
+ ```
428
+
429
+ ### Frontend Development
430
+
431
+ The frontend is a Vite + React 18 + TypeScript + Tailwind CSS app. To work on it:
432
+
433
+ ```bash
434
+ cd frontend
435
+ npm install
436
+ npm run dev # Start Vite dev server with hot reload
437
+ ```
438
+
439
+ During frontend development, the app renders with an empty data payload. To test with real data, generate a dashboard from a Rails app and copy the JSON payload from the resulting HTML.
440
+
441
+ ### Building the Frontend
442
+
443
+ ```bash
444
+ cd frontend
445
+ npm run build
446
+ ```
447
+
448
+ This builds a single self-contained HTML file (via `vite-plugin-singlefile`) to `lib/rails_visualizer/assets/dist/index.html`. This built file is committed to the repository so end users never need Node.js.
449
+
450
+ ### Project Structure
451
+
452
+ ```
453
+ lib/
454
+ rails_visualizer.rb # Entry point
455
+ rails_visualizer/
456
+ version.rb # VERSION constant
457
+ configuration.rb # All configurable options
458
+ railtie.rb # Loads rake task into Rails
459
+ path_helper.rb # Shared source file path resolution
460
+ introspector.rb # Orchestrator: parallel + fork-based
461
+ routes_inspector.rb # Route introspection
462
+ controllers_inspector.rb # Controller introspection
463
+ jobs_inspector.rb # ActiveJob + Sidekiq introspection
464
+ mailers_inspector.rb # Mailer introspection
465
+ migrations_inspector.rb # Migration status introspection
466
+ gems_inspector.rb # Bundler dependency introspection
467
+ serializer.rb # Ruby Hash → camelCase JSON
468
+ renderer.rb # JSON injection into HTML template
469
+ schema/
470
+ cache.rb # Bulk DB metadata (PG-optimized)
471
+ index_inspector.rb # Per-model index lookup
472
+ model_inspector.rb # Full model introspection
473
+ assets/dist/index.html # Pre-built frontend (committed)
474
+ tasks/
475
+ rails_visualizer.rake # The rake task
476
+
477
+ frontend/ # React source (dev only, not shipped)
478
+ src/
479
+ main.tsx # App bootstrap
480
+ App.tsx # Tab bar + tab routing
481
+ types.ts # TypeScript interfaces
482
+ hooks/useTheme.ts # Theme persistence
483
+ components/ # One component per tab + shared UI
484
+ utils/ # Layout, search, tree, dead code detection
485
+
486
+ spec/ # RSpec test suite
487
+ dummy/ # Minimal Rails app for testing
488
+ rails_visualizer/ # Inspector specs
489
+ ```
490
+
491
+ ## Contributing
492
+
493
+ 1. Fork the repository.
494
+ 2. Create a feature branch (`git checkout -b feature/my-feature`).
495
+ 3. Make your changes with full test coverage and no RuboCop offenses.
496
+ 4. Run the test suite and linter:
497
+
498
+ ```bash
499
+ bundle exec rspec
500
+ bundle exec rubocop
501
+ ```
502
+
503
+ 5. Open a pull request.
504
+
505
+ Please keep each PR focused. Bug fixes and well-scoped features are most likely to be merged quickly.
506
+
507
+ ## License
508
+
509
+ [MIT License](LICENSE.txt) &copy; 2026 Raj Kamal Lashkari