RailsVisualizer
One command. A full interactive dashboard for your Rails app.
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.
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.
Table of Contents
- Installation
- Quick Start
- Dashboard Tabs
- Configuration
- Health Checks
- How It Works
- Performance
- Compatibility
- FAQ
- Development
- Contributing
- License
Installation
Add rails_visualizer to your Gemfile. Since it only introspects the app and is never needed in production, place it in the development group:
group :development do
gem 'rails_visualizer'
end
Then run:
bundle install
That's it — no generators, no migrations, no configuration files needed.
Quick Start
bundle exec rake rails_visualizer
This single command will:
- Eager-load your Rails application.
- Introspect models, routes, controllers, jobs, mailers, migrations, and gems.
- Generate a self-contained HTML file at
tmp/rails_visualizer/index.html. - Open it in your default browser automatically.
Example output:
RailsVisualizer: Introspecting app...
✓ 47 models
✓ 128 routes
✓ 12 jobs
⚠ 31 controllers (3 actions without route)
⚠ 64 migrations (2 pending migrations)
✓ 4 mailers
RailsVisualizer: Rendering...
RailsVisualizer: Done → tmp/rails_visualizer/index.html
The generated HTML file is completely standalone — email it, commit it, drop it in Slack, or open it on any machine. No server required.
Dashboard Tabs
Overview
The landing tab gives you a bird's-eye view of your entire application:
- 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.). - 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.
- 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 for the full list.
Gems
Displays every dependency from your Gemfile:
- Name, version, and version constraint (e.g.
~> 7.0). - Summary pulled from the gem's metadata.
- Environment groups — color-coded chips for Common, Development, Test, and Production.
- Source tags — shows non-standard sources like
github: owner/repo,branch: main,path: engines/erp, orrequire: false. - Homepage link — external link icon for each gem.
- Filters — filter by environment group (Common, Development, Test, Production).
- Search — search across gem name, summary, and version.
Routes
Shows every route defined in config/routes.rb:
- HTTP verb — color-coded badge (GET green, POST blue, PATCH/PUT amber, DELETE red).
- Path — with
:paramsegments highlighted and(format)segments dimmed. - Controller#action — linked pair showing the target.
- Route name — the named helper (e.g.
edit_user). - Constraints — any route constraints displayed as chips.
- Orphaned route detection — routes pointing to non-existent controllers are flagged with a red "Orphaned" badge.
- Filters — toggle by HTTP verb (GET, POST, PATCH, PUT, DELETE) and an "Issues only" toggle to show only orphaned routes.
- Copy and Open in editor buttons for path and controller file.
Controllers
Namespace-grouped tree view of all your ActionController classes:
- 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.
- 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.
- Callbacks —
before_action,after_action, andaround_actionwith full metadata:only:andexcept:restrictionsif:andunless:conditions- Inherited callback tracking (shows which parent class defined it)
- Custom Proc condition indicator
- Public helpers — non-routable public methods (ending in
?or=) that might need visibility changes. - Superclass shown for each controller.
- Issues only toggle to filter down to controllers with unrouted actions.
Models
The richest tab, with two view modes:
List View
A namespace-grouped tree of all ActiveRecord models. Click any model to open a detail sidebar showing:
- Columns — name, type, nullability, default value, index info, and enum values.
- Associations —
has_many,belongs_to,has_one,has_many :through, andhas_and_belongs_to_manywith class name, foreign key,dependent:,as:(polymorphic), andthrough:details. - Validations — each validator with its kind, attributes, options, and validator class.
- Enums — enum name and all possible values.
- Scopes — named scopes defined in the model file.
- Callbacks — lifecycle callbacks (
before_save,after_create,around_destroy, etc.) with the owning module/concern if inherited.
Canvas View (ER Diagram)
An interactive React Flow canvas that renders your schema as an entity-relationship diagram:
- Model nodes — cards showing the model name and its columns with types and constraints.
- Association edges — labeled, color-coded lines between related models.
- Automatic layout — powered by Dagre for clean graph arrangement.
- Zoom, pan, and minimap — navigate large schemas with ease.
- Click-to-select — click any model node to open the detail sidebar.
Both views support:
- Search — filter models by name or table name.
- Issues only toggle — filter to models without any validations.
Migrations
Lists every migration file in db/migrate/:
- Status — green "Applied" badge or red "Pending" badge.
- Human-readable name — e.g. "Create Users" from
20240101_create_users.rb. - Version timestamp — parsed into a readable date.
- Current version indicator on the latest applied migration.
- Filter — by status (Applied, Pending) and search by name or version.
- Open in editor button for each migration file.
Jobs
Covers both ActiveJob classes and Sidekiq workers:
- Namespace tree — jobs grouped by
::module separators into a collapsible tree. - Queue — color-coded badge per queue name.
- ActiveJob details — queue name, priority,
retry_onhandlers, anddiscard_onconfiguration. - Sidekiq details — queue, retry setting, and uniqueness configuration. Workers with retries disabled get an amber warning.
- Adapter info — shows the configured queue adapter (Sidekiq, GoodJob, Solid Queue, etc.) with a description.
- Filter — by queue name, and an "Issues only" toggle for Sidekiq workers with retries disabled.
Mailers
Namespace tree of all ActionMailer classes:
- Email actions — each mailer method displayed as a pill.
- Inherited actions — collapsible section showing email methods inherited from parent mailers, grouped by the defining class.
- Default from — the configured
default from:address. Mailers without one are flagged. - Default reply-to — if configured.
- Layout — the mailer layout name.
- Callbacks —
before_action,after_action, andaround_actionon the mailer. - Abstract detection — mailers with no own email methods that serve as base classes are marked as abstract.
- Issues only toggle to filter to mailers without a
default_from.
Configuration
Create an initializer to customize any defaults. All settings are optional:
# config/initializers/rails_visualizer.rb
RailsVisualizer.configure do |config|
# Exclude specific model class names from introspection.
# Useful for internal/legacy models you don't want in the dashboard.
config.excluded_models = ['AuditLog', 'InternalSession']
# Exclude specific controller class names.
config.excluded_controllers = ['HealthCheckController', 'Admin::InternalController']
# Exclude specific job class names.
config.excluded_jobs = ['LegacyCleanupJob']
# Exclude specific mailer class names.
config.excluded_mailers = ['InternalNotifier']
# Exclude routes whose paths start with these prefixes.
# Handy for mounted engines like Sidekiq Web or ActiveAdmin.
config.excluded_route_paths = ['/admin', '/sidekiq']
# Directory where the HTML file is written (relative to Rails.root).
config.output_path = 'tmp/rails_visualizer'
# Output filename.
config.filename = 'index.html'
# Automatically open the browser after generation. Set to false for CI or scripts.
config.open_browser = true
# Default color theme for the dashboard. Users can change it in the UI.
# :light or :dark
config.theme = :light
# Use fork-based parallel workers for model inspection on large apps.
# Disable if forking causes issues with your database driver or environment.
config.parallel = true
end
Configuration Options Reference
| Option | Type | Default | Description |
|---|---|---|---|
excluded_models |
Array<String> |
[] |
Model class names to exclude |
excluded_controllers |
Array<String> |
[] |
Controller class names to exclude |
excluded_jobs |
Array<String> |
[] |
Job class names to exclude |
excluded_mailers |
Array<String> |
[] |
Mailer class names to exclude |
excluded_route_paths |
Array<String> |
[] |
Route path prefixes to exclude |
output_path |
String |
'tmp/rails_visualizer' |
Output directory (relative to Rails.root) |
filename |
String |
'index.html' |
Output file name |
open_browser |
Boolean |
true |
Auto-open browser after generation |
theme |
Symbol |
:light |
Default theme (:light or :dark) |
parallel |
Boolean |
true |
Enable fork-based parallel model inspection |
Disabling Browser Auto-Open
If you're running in CI, scripting, or just want the file without opening a browser:
RailsVisualizer.configure do |config|
config.open_browser = false
end
Excluding Mounted Engine Routes
Many apps mount engines like Sidekiq Web, ActiveAdmin, or Letter Opener that add many routes you may not want to visualize:
RailsVisualizer.configure do |config|
config.excluded_route_paths = ['/admin', '/sidekiq', '/letter_opener']
end
Health Checks
The Overview tab runs automated health checks across your application and surfaces issues at a glance. Each check has a severity level:
| Check | Severity | Passes when |
|---|---|---|
| Orphaned routes | Error | All routes point to a known controller class |
| Unrouted actions | Warning | All public controller actions have a matching route |
| Models without validations | Warning | All models have at least one validation |
| Pending migrations | Error | All migrations have been applied |
| Sidekiq retries disabled | Warning | All Sidekiq workers have retries enabled |
| Mailers without default_from | Warning | All mailers have a default from: address |
Each failing check has a "Go to" button that navigates to the relevant tab where you can see the full details.
How It Works
Rake task
└─ Introspector
├─ eager_load! (load all classes)
├─ 5 parallel Threads (routes, controllers, jobs, mailers, gems)
├─ Schema::Cache (bulk DB metadata in 2 SQL queries on PG)
├─ MigrationsInspector
└─ ModelInspector (fork-based workers for 50+ models)
└─ per-model: columns, associations, validations, enums, scopes, callbacks
└─ Serializer (Ruby Hash → camelCase JSON)
└─ Renderer (inject JSON into pre-built React HTML)
└─ Write tmp/rails_visualizer/index.html
└─ Open browser
Step by Step
Eager-load —
Rails.application.eager_load!ensures all classes are defined before introspection begins.Parallel introspection — five inspectors run in parallel threads:
RoutesInspector,ControllersInspector,JobsInspector,MailersInspector, andGemsInspector. Since these are I/O-bound (filesystem reads, route table traversal), threads give a meaningful speedup even with the GIL.Database metadata —
Schema::Cachebulk-loads all column and index metadata. On PostgreSQL, this runs two parallel SQL queries againstinformation_schema.columnsandpg_indexwith a SQL-level table filter for maximum speed. Other adapters use a per-table fallback through the ActiveRecord API.Model inspection —
Schema::ModelInspectorinspects 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 viaMarshal.dump/loadthrough temp files.Serialization —
Serializerconverts the Ruby hash to JSON, recursively transforming allsnake_casekeys tocamelCasewith memoized key conversion.Rendering —
Rendererreads the pre-built React HTML template and injects the JSON via a placeholder<script>tag, producing a single self-contained HTML file.Output — the file is written to disk and optionally opened in the browser.
Error Resilience
Every inspector follows the same safety pattern:
def call
# ... introspection logic
rescue StandardError
[] # safe default — never crash the host app
end
Individual model/controller/job failures are caught and skipped. Warnings are printed via warn "[RailsVisualizer] ..." but never raise.
Performance
RailsVisualizer is designed to be fast even on large codebases:
- Parallel threads for I/O-bound inspectors (routes, controllers, jobs, mailers, gems).
- Fork-based workers for CPU-bound model inspection when you have 50+ models (automatically scales up to 8 processes based on CPU count).
- Bulk SQL on PostgreSQL — two queries total for all column and index metadata, instead of per-table queries.
- Shared caches — file content, method source locations, and enum lookups are cached across models to avoid redundant work.
- Memoized key conversion — the Serializer reuses the same ~30 camelCase key transforms across thousands of objects.
If you experience issues with fork-based parallelism (e.g. database driver compatibility), disable it:
RailsVisualizer.configure do |config|
config.parallel = false
end
Compatibility
- Ruby >= 3.0
- Rails >= 7.0 (tested on 7.0, 7.1, 7.2, 8.0+)
- PostgreSQL — optimized with bulk-loaded parallel SQL queries for maximum speed
- MySQL — full support via per-table ActiveRecord API fallback
- SQLite — full support via per-table ActiveRecord API fallback
- Any other ActiveRecord adapter — per-table fallback with identical output
- Zero runtime dependencies — the gem adds nothing to your production bundle
- ActionController::API — API-only apps are fully supported alongside traditional apps
- Sidekiq — Sidekiq workers are detected alongside ActiveJob classes
FAQ
Does this affect my production app?
No. The gem should be in the :development group and is only activated when you explicitly run the Rake task.
Do I need Node.js? No. The frontend is pre-built into a single HTML file and committed to the gem. End users never need Node.js.
Can I share the generated HTML file? 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.
Does it work with API-only Rails apps?
Yes. Both ActionController::Base and ActionController::API controllers are introspected.
What about STI / abstract models? Abstract models are excluded from introspection by default. STI models are included and shown with their own columns and associations.
My app has 500+ models — will it be slow? 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.
Can I customize the output path? Yes. See the Configuration section. You can change both the directory and filename.
The browser didn't open automatically.
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.
How do I regenerate after code changes?
Just run bundle exec rake rails_visualizer again. The file is overwritten each time.
Does it detect issues?
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.
Development
Clone the repo and install dependencies:
git clone https://github.com/rajkamallashkari/rails_visualizer.git
cd rails_visualizer
bundle install
Running Tests
bundle exec rspec
The test suite boots a minimal dummy Rails app with an in-memory SQLite database, so no external database is needed.
Running RuboCop
bundle exec rubocop
Frontend Development
The frontend is a Vite + React 18 + TypeScript + Tailwind CSS app. To work on it:
cd frontend
npm install
npm run dev # Start Vite dev server with hot reload
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.
Building the Frontend
cd frontend
npm run build
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.
Project Structure
lib/
rails_visualizer.rb # Entry point
rails_visualizer/
version.rb # VERSION constant
configuration.rb # All configurable options
railtie.rb # Loads rake task into Rails
path_helper.rb # Shared source file path resolution
introspector.rb # Orchestrator: parallel + fork-based
routes_inspector.rb # Route introspection
controllers_inspector.rb # Controller introspection
jobs_inspector.rb # ActiveJob + Sidekiq introspection
mailers_inspector.rb # Mailer introspection
migrations_inspector.rb # Migration status introspection
gems_inspector.rb # Bundler dependency introspection
serializer.rb # Ruby Hash → camelCase JSON
renderer.rb # JSON injection into HTML template
schema/
cache.rb # Bulk DB metadata (PG-optimized)
index_inspector.rb # Per-model index lookup
model_inspector.rb # Full model introspection
assets/dist/index.html # Pre-built frontend (committed)
tasks/
rails_visualizer.rake # The rake task
frontend/ # React source (dev only, not shipped)
src/
main.tsx # App bootstrap
App.tsx # Tab bar + tab routing
types.ts # TypeScript interfaces
hooks/useTheme.ts # Theme persistence
components/ # One component per tab + shared UI
utils/ # Layout, search, tree, dead code detection
spec/ # RSpec test suite
dummy/ # Minimal Rails app for testing
rails_visualizer/ # Inspector specs
Contributing
- Fork the repository.
- Create a feature branch (
git checkout -b feature/my-feature). - Make your changes with full test coverage and no RuboCop offenses.
- Run the test suite and linter:
bundle exec rspec
bundle exec rubocop
- Open a pull request.
Please keep each PR focused. Bug fixes and well-scoped features are most likely to be merged quickly.
License
MIT License © 2026 Raj Kamal Lashkari