rails-schema 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 +7 -0
- data/LICENSE.txt +21 -0
- data/PROJECT.md +322 -0
- data/README.md +77 -0
- data/Rakefile +12 -0
- data/docs/index.html +1015 -0
- data/docs/screenshot.png +0 -0
- data/lib/rails/schema/assets/app.js +487 -0
- data/lib/rails/schema/assets/style.css +473 -0
- data/lib/rails/schema/assets/template.html.erb +53 -0
- data/lib/rails/schema/assets/vendor/d3.min.js +2 -0
- data/lib/rails/schema/configuration.rb +17 -0
- data/lib/rails/schema/extractor/association_reader.rb +44 -0
- data/lib/rails/schema/extractor/column_reader.rb +37 -0
- data/lib/rails/schema/extractor/model_scanner.rb +108 -0
- data/lib/rails/schema/extractor/schema_file_parser.rb +107 -0
- data/lib/rails/schema/railtie.rb +17 -0
- data/lib/rails/schema/renderer/html_generator.rb +71 -0
- data/lib/rails/schema/transformer/edge.rb +33 -0
- data/lib/rails/schema/transformer/graph_builder.rb +60 -0
- data/lib/rails/schema/transformer/node.rb +25 -0
- data/lib/rails/schema/version.rb +7 -0
- data/lib/rails/schema.rb +43 -0
- data/sig/rails/schema.rbs +6 -0
- metadata +96 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 1275bccb3e5144d351dcf4445209299ee269dfae8e75b4176e8a91bb85b5ccc2
|
|
4
|
+
data.tar.gz: 2ba3e983963eaef3a933ba9d99eebd7b3221acdaca492212ddda04d5a0354122
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: bade47644111e000883867b876dad54b59aa07df5800719185c48cd9d2307fa030d3d1df38c00a738be94bd2c37426bbe5d181729dc9b0995872103449332e1b
|
|
7
|
+
data.tar.gz: ee1eaa1f3050778be38ae59a69269b93658e149466cc135ec7eb58cbc34cbf2ec814ea99d665777887c64ff341440351a63ac9707a791add32e9fb30d152ab52
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Andrei Kislichenko
|
|
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
|
|
13
|
+
all 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
|
|
21
|
+
THE SOFTWARE.
|
data/PROJECT.md
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
# Rails::Schema — Project Design
|
|
2
|
+
|
|
3
|
+
**A Ruby gem that generates an interactive HTML/JS/CSS page to visualize the database schema of a Rails application.**
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Gem Overview
|
|
8
|
+
|
|
9
|
+
**Name:** `rails-schema`
|
|
10
|
+
**Module:** `Rails::Schema`
|
|
11
|
+
**Version:** `0.1.0`
|
|
12
|
+
|
|
13
|
+
Rails::Schema introspects a Rails app's models, associations, and database columns at runtime, then generates a single self-contained HTML file with an interactive, explorable entity-relationship diagram. No external server, no SaaS dependency — just one command and a browser.
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Rake task
|
|
17
|
+
rake rails_schema:generate
|
|
18
|
+
|
|
19
|
+
# Programmatic
|
|
20
|
+
Rails::Schema.generate(output: "docs/schema.html")
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 2. Architecture
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
┌──────────────────────────────────────────────────────┐
|
|
29
|
+
│ rails-schema gem │
|
|
30
|
+
├──────────────┬──────────────┬────────────────────────┤
|
|
31
|
+
│ Extractor │ Transformer │ Renderer │
|
|
32
|
+
│ (Ruby) │ (Ruby) │ (ERB → HTML/JS/CSS) │
|
|
33
|
+
├──────────────┼──────────────┼────────────────────────┤
|
|
34
|
+
│ Reads Rails │ Builds a │ Produces a single │
|
|
35
|
+
│ models, │ normalized │ self-contained .html │
|
|
36
|
+
│ reflections, │ graph JSON │ file with embedded │
|
|
37
|
+
│ schema.rb, │ structure │ JS app + CSS │
|
|
38
|
+
│ columns │ │ │
|
|
39
|
+
└──────────────┴──────────────┴────────────────────────┘
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 2.1 Layer Breakdown
|
|
43
|
+
|
|
44
|
+
| Layer | Responsibility | Key Classes |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| **Extractor** | Introspects Rails environment; collects models, columns, associations | `Rails::Schema::Extractor::ModelScanner`, `ColumnReader`, `AssociationReader`, `SchemaFileParser` |
|
|
47
|
+
| **Transformer** | Normalizes extracted data into a serializable graph structure (nodes + edges + metadata) | `Rails::Schema::Transformer::GraphBuilder`, `Node`, `Edge` |
|
|
48
|
+
| **Renderer** | Takes the graph data and injects it into an HTML/JS/CSS template using ERB | `Rails::Schema::Renderer::HtmlGenerator` |
|
|
49
|
+
| **Railtie** | Provides the `rails_schema:generate` rake task | `Rails::Schema::Railtie` |
|
|
50
|
+
|
|
51
|
+
### 2.2 Generation Pipeline
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
def generate(output: nil)
|
|
55
|
+
schema_data = Extractor::SchemaFileParser.new.parse
|
|
56
|
+
models = Extractor::ModelScanner.new(schema_data: schema_data).scan
|
|
57
|
+
column_reader = Extractor::ColumnReader.new(schema_data: schema_data)
|
|
58
|
+
graph_data = Transformer::GraphBuilder.new(column_reader: column_reader).build(models)
|
|
59
|
+
generator = Renderer::HtmlGenerator.new(graph_data: graph_data)
|
|
60
|
+
generator.render_to_file(output)
|
|
61
|
+
end
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 3. Data Extraction Strategy
|
|
67
|
+
|
|
68
|
+
### 3.1 Sources of Truth
|
|
69
|
+
|
|
70
|
+
1. **`db/schema.rb` parsing** — `SchemaFileParser` parses the schema file line-by-line with regex to extract table names, column definitions (name, type, nullable, default), and primary key info. This is attempted first and used as a fast, database-free source.
|
|
71
|
+
2. **ActiveRecord reflection API** — `AssociationReader` uses `Model.reflect_on_all_associations` for associations (`has_many`, `belongs_to`, `has_one`, `has_and_belongs_to_many`), including `:through` and `:polymorphic`.
|
|
72
|
+
3. **`Model.columns`** — `ColumnReader` falls back to `model.columns` via ActiveRecord when a table is not found in schema_data.
|
|
73
|
+
|
|
74
|
+
### 3.2 Model Discovery
|
|
75
|
+
|
|
76
|
+
`ModelScanner` discovers models by:
|
|
77
|
+
|
|
78
|
+
1. Calling `Rails.application.eager_load!` (with Zeitwerk support and multiple fallback strategies)
|
|
79
|
+
2. Collecting `ActiveRecord::Base.descendants`
|
|
80
|
+
3. Filtering out abstract classes, anonymous classes, and models without known tables
|
|
81
|
+
4. Applying `exclude_models` configuration (supports wildcard prefix matching like `"ActiveStorage::*"`)
|
|
82
|
+
5. Returning models sorted by name
|
|
83
|
+
|
|
84
|
+
When `schema_data` is available, table existence is checked against parsed schema data instead of hitting the database.
|
|
85
|
+
|
|
86
|
+
### 3.3 Schema File Parser
|
|
87
|
+
|
|
88
|
+
`SchemaFileParser` provides database-free column extraction:
|
|
89
|
+
|
|
90
|
+
- Parses `create_table` blocks from `db/schema.rb`
|
|
91
|
+
- Extracts column types, names, nullability, and defaults (string, numeric, boolean)
|
|
92
|
+
- Handles custom primary key types (`id: :uuid`, `id: :bigint`) and `id: false`
|
|
93
|
+
- Skips index definitions
|
|
94
|
+
|
|
95
|
+
### 3.4 Intermediate Data Format (JSON Graph)
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"nodes": [
|
|
100
|
+
{
|
|
101
|
+
"id": "User",
|
|
102
|
+
"table": "users",
|
|
103
|
+
"columns": [
|
|
104
|
+
{ "name": "id", "type": "bigint", "primary": true },
|
|
105
|
+
{ "name": "email", "type": "string", "nullable": false },
|
|
106
|
+
{ "name": "name", "type": "string", "nullable": true }
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
],
|
|
110
|
+
"edges": [
|
|
111
|
+
{
|
|
112
|
+
"from": "User",
|
|
113
|
+
"to": "Post",
|
|
114
|
+
"type": "has_many",
|
|
115
|
+
"through": null,
|
|
116
|
+
"foreign_key": "user_id",
|
|
117
|
+
"polymorphic": false,
|
|
118
|
+
"label": "posts"
|
|
119
|
+
}
|
|
120
|
+
],
|
|
121
|
+
"metadata": {
|
|
122
|
+
"rails_version": "7.2.0",
|
|
123
|
+
"generated_at": "2026-02-15T12:00:00Z",
|
|
124
|
+
"model_count": 42
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 4. Interactive Frontend Design
|
|
132
|
+
|
|
133
|
+
The generated HTML file is a **single self-contained file** — no CDN dependencies, no network requests. All JS and CSS are inlined. The JSON graph is embedded as a `<script>` tag.
|
|
134
|
+
|
|
135
|
+
### 4.1 Technology Choices
|
|
136
|
+
|
|
137
|
+
| Concern | Choice | Rationale |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| Graph rendering | **SVG + d3-force** (vendored/minified) | DOM-level interactivity, good for typical schema sizes |
|
|
140
|
+
| Layout algorithm | Force-directed (d3-force) | Natural clustering of related models |
|
|
141
|
+
| UI framework | Vanilla JS | Zero dependencies, small file size |
|
|
142
|
+
| Styling | CSS custom properties + embedded stylesheet | Theming support, dark/light mode |
|
|
143
|
+
|
|
144
|
+
### 4.2 Implemented Interactive Features
|
|
145
|
+
|
|
146
|
+
#### A. Model Selector Panel (left sidebar, 280px)
|
|
147
|
+
|
|
148
|
+
- Searchable list of all models with filtering
|
|
149
|
+
- Multi-select checkboxes to toggle visibility
|
|
150
|
+
- Model count display
|
|
151
|
+
|
|
152
|
+
#### B. Canvas / Diagram Area (center)
|
|
153
|
+
|
|
154
|
+
- **Nodes** = model cards showing:
|
|
155
|
+
- Model name (bold header)
|
|
156
|
+
- Column list (expandable/collapsible — collapsed by default)
|
|
157
|
+
- Primary key highlighted
|
|
158
|
+
- Column types shown in a muted typeface
|
|
159
|
+
- **Edges** = association lines:
|
|
160
|
+
- Color-coded by association type
|
|
161
|
+
- Labels on hover (association name + foreign key)
|
|
162
|
+
- **Force-directed layout** that stabilizes, then allows manual drag-and-drop
|
|
163
|
+
|
|
164
|
+
#### C. Zoom & Navigation
|
|
165
|
+
|
|
166
|
+
- Scroll-wheel zoom with smooth interpolation
|
|
167
|
+
- Pinch-to-zoom on trackpads
|
|
168
|
+
- Fit-to-screen button
|
|
169
|
+
- Zoom-to-selection (click a model in sidebar to center on it)
|
|
170
|
+
|
|
171
|
+
#### D. Focus Mode
|
|
172
|
+
|
|
173
|
+
When a user clicks on a model node:
|
|
174
|
+
|
|
175
|
+
1. The selected model and its directly associated models are highlighted
|
|
176
|
+
2. All other nodes and edges fade to reduced opacity
|
|
177
|
+
3. A detail panel (right sidebar, 320px) shows full column/association info
|
|
178
|
+
4. Press `Esc` or click background to exit
|
|
179
|
+
|
|
180
|
+
#### E. Toolbar (48px)
|
|
181
|
+
|
|
182
|
+
- Dark / Light theme toggle (respects `prefers-color-scheme`)
|
|
183
|
+
- Fit-to-screen button
|
|
184
|
+
- Keyboard shortcuts: `/` to focus search, `Esc` to deselect
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## 5. Configuration
|
|
189
|
+
|
|
190
|
+
```ruby
|
|
191
|
+
# config/initializers/rails_schema.rb
|
|
192
|
+
Rails::Schema.configure do |config|
|
|
193
|
+
config.output_path = "docs/schema.html" # Output file location
|
|
194
|
+
config.exclude_models = [] # Models to exclude (supports "Namespace::*" wildcards)
|
|
195
|
+
config.title = "Database Schema" # Page title
|
|
196
|
+
config.theme = :auto # :light, :dark, :auto
|
|
197
|
+
config.expand_columns = false # Start with columns expanded
|
|
198
|
+
end
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## 6. Gem Structure
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
rails-schema/
|
|
207
|
+
├── lib/
|
|
208
|
+
│ ├── rails/schema.rb # Entry point, configuration DSL, generate method
|
|
209
|
+
│ └── rails/schema/
|
|
210
|
+
│ ├── version.rb # VERSION = "0.1.0"
|
|
211
|
+
│ ├── configuration.rb # Config object (5 attributes)
|
|
212
|
+
│ ├── railtie.rb # Rails integration, rake task
|
|
213
|
+
│ ├── extractor/
|
|
214
|
+
│ │ ├── model_scanner.rb # Discovers AR models
|
|
215
|
+
│ │ ├── association_reader.rb # Reads reflections
|
|
216
|
+
│ │ ├── column_reader.rb # Reads columns (schema_data or AR)
|
|
217
|
+
│ │ └── schema_file_parser.rb # Parses db/schema.rb
|
|
218
|
+
│ ├── transformer/
|
|
219
|
+
│ │ ├── graph_builder.rb # Builds node/edge graph
|
|
220
|
+
│ │ ├── node.rb # Value object
|
|
221
|
+
│ │ └── edge.rb # Value object
|
|
222
|
+
│ ├── renderer/
|
|
223
|
+
│ │ └── html_generator.rb # ERB rendering, asset inlining
|
|
224
|
+
│ └── assets/
|
|
225
|
+
│ ├── template.html.erb # Main HTML template
|
|
226
|
+
│ ├── app.js # Interactive frontend (vanilla JS)
|
|
227
|
+
│ ├── style.css # Stylesheet with CSS custom properties
|
|
228
|
+
│ └── vendor/
|
|
229
|
+
│ └── d3.min.js # Vendored d3 library
|
|
230
|
+
├── spec/
|
|
231
|
+
│ ├── spec_helper.rb
|
|
232
|
+
│ ├── support/
|
|
233
|
+
│ │ └── test_models.rb # User, Post, Comment, Tag models
|
|
234
|
+
│ └── rails/schema/
|
|
235
|
+
│ ├── rails_schema_spec.rb
|
|
236
|
+
│ ├── configuration_spec.rb
|
|
237
|
+
│ ├── extractor/
|
|
238
|
+
│ │ ├── model_scanner_spec.rb
|
|
239
|
+
│ │ ├── column_reader_spec.rb
|
|
240
|
+
│ │ ├── association_reader_spec.rb
|
|
241
|
+
│ │ └── schema_file_parser_spec.rb
|
|
242
|
+
│ ├── transformer/
|
|
243
|
+
│ │ └── graph_builder_spec.rb
|
|
244
|
+
│ └── renderer/
|
|
245
|
+
│ └── html_generator_spec.rb
|
|
246
|
+
├── Gemfile
|
|
247
|
+
├── rails-schema.gemspec
|
|
248
|
+
├── LICENSE.txt
|
|
249
|
+
└── README.md
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## 7. Key Design Decisions
|
|
255
|
+
|
|
256
|
+
### Why a single HTML file?
|
|
257
|
+
|
|
258
|
+
- **Zero deployment friction** — open in any browser, share via Slack/email, commit to repo
|
|
259
|
+
- **Offline-first** — works on airplane mode, no CDN failures
|
|
260
|
+
- **Portable** — CI can generate it, GitHub Pages can host it, anyone can view it
|
|
261
|
+
|
|
262
|
+
### Why not a mounted Rails engine?
|
|
263
|
+
|
|
264
|
+
A mounted engine requires a running server. A static file can be generated in CI, committed to the repo, and opened by anyone — including non-developers looking at a data model.
|
|
265
|
+
|
|
266
|
+
### Why parse schema.rb?
|
|
267
|
+
|
|
268
|
+
Parsing `db/schema.rb` allows column extraction without a database connection. This means the gem can work in CI environments or development setups where the database isn't running. It also avoids eager-loading the entire app just to read column metadata.
|
|
269
|
+
|
|
270
|
+
### Why force-directed layout?
|
|
271
|
+
|
|
272
|
+
It handles unknown schemas gracefully — you don't need to pre-define positions. Combined with drag-and-drop repositioning, it gives the best default experience.
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## 8. Dependencies
|
|
277
|
+
|
|
278
|
+
```ruby
|
|
279
|
+
# rails-schema.gemspec
|
|
280
|
+
spec.add_dependency "activerecord", ">= 6.0"
|
|
281
|
+
spec.add_dependency "railties", ">= 6.0"
|
|
282
|
+
|
|
283
|
+
# Development
|
|
284
|
+
# rspec (~> 3.0), rubocop (~> 1.21), sqlite3
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
**Zero runtime JS dependencies shipped to the user** — d3 is vendored and minified into the template. The HTML file has no external requests.
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## 9. Testing Strategy
|
|
292
|
+
|
|
293
|
+
| Layer | Approach |
|
|
294
|
+
|---|---|
|
|
295
|
+
| Extractor | Unit tests with in-memory SQLite models (User, Post, Comment, Tag) |
|
|
296
|
+
| Transformer | Pure Ruby unit tests — graph building, edge filtering |
|
|
297
|
+
| Renderer | Output tests — verify HTML structure, embedded data, script injection safety |
|
|
298
|
+
| Configuration | Unit tests for defaults and attribute setting |
|
|
299
|
+
|
|
300
|
+
**66 tests, all passing.** Run with `bundle exec rspec`.
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## 10. Future Enhancements (Roadmap)
|
|
305
|
+
|
|
306
|
+
1. **CLI executable** — `bundle exec rails_schema` binary for standalone usage
|
|
307
|
+
2. **Live mode** — a mounted Rails engine with hot-reload when migrations run
|
|
308
|
+
3. **Additional layout modes** — hierarchical, circular, grid
|
|
309
|
+
4. **Validation extraction** — read `Model.validators` for presence, uniqueness constraints
|
|
310
|
+
5. **STI handling** — group models sharing a table, show children as badges
|
|
311
|
+
6. **Concern extraction** — display included modules on model nodes
|
|
312
|
+
7. **Export options** — PNG, SVG, Mermaid ER diagram, raw JSON
|
|
313
|
+
8. **Schema diff** — compare two generated JSONs and highlight changes
|
|
314
|
+
9. **Multi-database support** — Rails 6+ multi-DB configs
|
|
315
|
+
10. **Minimap** — thumbnail overview for large schemas
|
|
316
|
+
11. **Permalink / State URL** — encode view state in URL hash for sharing
|
|
317
|
+
12. **Advanced filtering** — `include_only`, namespace grouping, tag-based filters
|
|
318
|
+
13. **Custom CSS/JS injection** — user-provided assets inlined into output
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
*Document reflects the current implementation (v0.1.0). Future enhancements are aspirational and subject to refinement.*
|
data/README.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Rails::Schema
|
|
2
|
+
|
|
3
|
+
Interactive HTML visualization of your Rails database schema. Introspects your app's models, associations, and columns, then generates a single self-contained HTML file with an interactive entity-relationship diagram.
|
|
4
|
+
|
|
5
|
+
No external server, no CDN — just one command and a browser.
|
|
6
|
+
|
|
7
|
+
**[Live example](https://andrew2net.github.io/rails-schema/)** — generated from [Fizzy](https://www.fizzy.do), a modern spin on kanban for tracking just about anything, created by [37signals](https://37signals.com).
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
Add to your Gemfile:
|
|
14
|
+
|
|
15
|
+
```ruby
|
|
16
|
+
gem "rails-schema", group: :development
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Then run:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
bundle install
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### Rake task
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
rake rails_schema:generate
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
This generates `docs/schema.html` by default. Open it in your browser.
|
|
34
|
+
|
|
35
|
+
### Programmatic
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
Rails::Schema.generate(output: "docs/schema.html")
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Configuration
|
|
42
|
+
|
|
43
|
+
Create an initializer at `config/initializers/rails_schema.rb`:
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
Rails::Schema.configure do |config|
|
|
47
|
+
config.output_path = "docs/schema.html"
|
|
48
|
+
config.title = "My App Schema"
|
|
49
|
+
config.theme = :auto # :auto, :light, or :dark
|
|
50
|
+
config.expand_columns = false # start with columns collapsed
|
|
51
|
+
config.exclude_models = [
|
|
52
|
+
"ActiveStorage::Blob",
|
|
53
|
+
"ActiveStorage::Attachment",
|
|
54
|
+
"ActionMailbox::*" # wildcard prefix matching
|
|
55
|
+
]
|
|
56
|
+
end
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## How it works
|
|
60
|
+
|
|
61
|
+
The gem parses your `db/schema.rb` file to extract table and column information — **no database connection required**. It also introspects loaded ActiveRecord models for association metadata. This means the gem works even if you don't have a local database set up, as long as `db/schema.rb` is present (which is standard in Rails projects under version control).
|
|
62
|
+
|
|
63
|
+
## Features
|
|
64
|
+
|
|
65
|
+
- **No database required** — reads directly from `db/schema.rb`
|
|
66
|
+
- **Force-directed layout** — models cluster naturally by association density
|
|
67
|
+
- **Searchable sidebar** — filter models by name or table
|
|
68
|
+
- **Click-to-focus** — click a model to highlight its neighborhood, fading unrelated models
|
|
69
|
+
- **Detail panel** — full column list and associations for the selected model
|
|
70
|
+
- **Dark/light theme** — toggle or auto-detect from system preference
|
|
71
|
+
- **Zoom & pan** — scroll wheel, pinch, or buttons
|
|
72
|
+
- **Keyboard shortcuts** — `/` search, `Esc` deselect, `+/-` zoom, `F` fit to screen
|
|
73
|
+
- **Self-contained** — single HTML file with all CSS, JS, and data inlined
|
|
74
|
+
|
|
75
|
+
## License
|
|
76
|
+
|
|
77
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|