rails_lens 0.0.0 → 0.2.2

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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -0
  3. data/LICENSE.txt +2 -2
  4. data/README.md +463 -9
  5. data/exe/rails_lens +25 -0
  6. data/lib/rails_lens/analyzers/association_analyzer.rb +111 -0
  7. data/lib/rails_lens/analyzers/base.rb +35 -0
  8. data/lib/rails_lens/analyzers/best_practices_analyzer.rb +114 -0
  9. data/lib/rails_lens/analyzers/column_analyzer.rb +97 -0
  10. data/lib/rails_lens/analyzers/composite_keys.rb +62 -0
  11. data/lib/rails_lens/analyzers/database_constraints.rb +35 -0
  12. data/lib/rails_lens/analyzers/delegated_types.rb +129 -0
  13. data/lib/rails_lens/analyzers/enums.rb +34 -0
  14. data/lib/rails_lens/analyzers/error_handling.rb +66 -0
  15. data/lib/rails_lens/analyzers/foreign_key_analyzer.rb +47 -0
  16. data/lib/rails_lens/analyzers/generated_columns.rb +56 -0
  17. data/lib/rails_lens/analyzers/index_analyzer.rb +128 -0
  18. data/lib/rails_lens/analyzers/inheritance.rb +212 -0
  19. data/lib/rails_lens/analyzers/notes.rb +325 -0
  20. data/lib/rails_lens/analyzers/performance_analyzer.rb +110 -0
  21. data/lib/rails_lens/annotation_pipeline.rb +87 -0
  22. data/lib/rails_lens/cli.rb +176 -0
  23. data/lib/rails_lens/cli_error_handler.rb +86 -0
  24. data/lib/rails_lens/commands.rb +164 -0
  25. data/lib/rails_lens/connection.rb +133 -0
  26. data/lib/rails_lens/erd/column_type_formatter.rb +32 -0
  27. data/lib/rails_lens/erd/domain_color_mapper.rb +40 -0
  28. data/lib/rails_lens/erd/mysql_column_type_formatter.rb +19 -0
  29. data/lib/rails_lens/erd/postgresql_column_type_formatter.rb +19 -0
  30. data/lib/rails_lens/erd/visualizer.rb +329 -0
  31. data/lib/rails_lens/errors.rb +78 -0
  32. data/lib/rails_lens/extension_loader.rb +261 -0
  33. data/lib/rails_lens/extensions/base.rb +194 -0
  34. data/lib/rails_lens/extensions/closure_tree_ext.rb +157 -0
  35. data/lib/rails_lens/file_insertion_helper.rb +168 -0
  36. data/lib/rails_lens/mailer/annotator.rb +226 -0
  37. data/lib/rails_lens/mailer/extractor.rb +201 -0
  38. data/lib/rails_lens/model_detector.rb +252 -0
  39. data/lib/rails_lens/parsers/class_info.rb +46 -0
  40. data/lib/rails_lens/parsers/module_info.rb +33 -0
  41. data/lib/rails_lens/parsers/parser_result.rb +55 -0
  42. data/lib/rails_lens/parsers/prism_parser.rb +90 -0
  43. data/lib/rails_lens/parsers.rb +10 -0
  44. data/lib/rails_lens/providers/association_notes_provider.rb +11 -0
  45. data/lib/rails_lens/providers/base.rb +37 -0
  46. data/lib/rails_lens/providers/best_practices_notes_provider.rb +11 -0
  47. data/lib/rails_lens/providers/column_notes_provider.rb +11 -0
  48. data/lib/rails_lens/providers/composite_keys_provider.rb +11 -0
  49. data/lib/rails_lens/providers/database_constraints_provider.rb +11 -0
  50. data/lib/rails_lens/providers/delegated_types_provider.rb +11 -0
  51. data/lib/rails_lens/providers/enums_provider.rb +11 -0
  52. data/lib/rails_lens/providers/extension_notes_provider.rb +20 -0
  53. data/lib/rails_lens/providers/extensions_provider.rb +22 -0
  54. data/lib/rails_lens/providers/foreign_key_notes_provider.rb +11 -0
  55. data/lib/rails_lens/providers/generated_columns_provider.rb +11 -0
  56. data/lib/rails_lens/providers/index_notes_provider.rb +20 -0
  57. data/lib/rails_lens/providers/inheritance_provider.rb +23 -0
  58. data/lib/rails_lens/providers/notes_provider_base.rb +25 -0
  59. data/lib/rails_lens/providers/performance_notes_provider.rb +11 -0
  60. data/lib/rails_lens/providers/schema_provider.rb +61 -0
  61. data/lib/rails_lens/providers/section_provider_base.rb +28 -0
  62. data/lib/rails_lens/railtie.rb +17 -0
  63. data/lib/rails_lens/rake_bootstrapper.rb +18 -0
  64. data/lib/rails_lens/route/annotator.rb +268 -0
  65. data/lib/rails_lens/route/extractor.rb +133 -0
  66. data/lib/rails_lens/route/parser.rb +59 -0
  67. data/lib/rails_lens/schema/adapters/base.rb +345 -0
  68. data/lib/rails_lens/schema/adapters/database_info.rb +118 -0
  69. data/lib/rails_lens/schema/adapters/mysql.rb +279 -0
  70. data/lib/rails_lens/schema/adapters/postgresql.rb +197 -0
  71. data/lib/rails_lens/schema/adapters/sqlite3.rb +96 -0
  72. data/lib/rails_lens/schema/annotation.rb +144 -0
  73. data/lib/rails_lens/schema/annotation_manager.rb +202 -0
  74. data/lib/rails_lens/tasks/annotate.rake +35 -0
  75. data/lib/rails_lens/tasks/erd.rake +24 -0
  76. data/lib/rails_lens/tasks/mailers.rake +27 -0
  77. data/lib/rails_lens/tasks/routes.rake +27 -0
  78. data/lib/rails_lens/tasks/schema.rake +108 -0
  79. data/lib/rails_lens/version.rb +5 -0
  80. data/lib/rails_lens.rb +138 -5
  81. metadata +215 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fcb43319079a928ef9b2963e36a9c0931cead09cc08373203ee0d63906351095
4
- data.tar.gz: d3506a65d4148d5c64df830e3acad2520a9c46e63740749647044a153cbe08d8
3
+ metadata.gz: 41ebdd3c52cca1c77790aa896dcc5962acb92c44eec90a2dceeda98f310aefb7
4
+ data.tar.gz: 72e49695a796e9d030fd80aedab53d7dea055db82c98e8023a6a2bb4293e139f
5
5
  SHA512:
6
- metadata.gz: a30660d1a71551b405b1faece66f8bee82dfab2a5b0c2d8bef306e6f470b482dc7cc007afa77ebac066348ce5677909c47b92e2f7376079bb8495725823e609c
7
- data.tar.gz: c71955bef895d24e13f659a86483ea1da04c8aaf51408551b4cade42bcb4d102f5e84ea11059b87704988942f361f8a1f0b4bf5dae086eb22c6a9f2a5734f001
6
+ metadata.gz: d0e890e0ae21326d6176542668277a1c8e5d6336f013dec8cc8854f892c0136c6a40fb4557789dc661c47de70fbf82c0e59dcc75769b4a41e613f681e75f9a9f
7
+ data.tar.gz: d5c0d6aaecbd3a46986cc86507b3550347bd09e69f4126721fdb9acec05110a2f622fa2555d8c37151144efdd89ef5b87129576d3bc66c02f2b8cdd3404fcb77
data/CHANGELOG.md ADDED
@@ -0,0 +1,23 @@
1
+ # Changelog
2
+
3
+ ## [0.2.2](https://github.com/seuros/rails_lens/compare/rails_lens/v0.2.1...rails_lens/v0.2.2) (2025-07-31)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * remove from format from the erd visualize ([#5](https://github.com/seuros/rails_lens/issues/5)) ([c2efdc7](https://github.com/seuros/rails_lens/commit/c2efdc7011425fcd8b46dce54d811ce166b0c660))
9
+
10
+ ## [0.2.1](https://github.com/seuros/rails_lens/compare/rails_lens/v0.2.0...rails_lens/v0.2.1) (2025-07-30)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * resolve GitHub issue [#2](https://github.com/seuros/rails_lens/issues/2) CLI and provider errors ([6d92c67](https://github.com/seuros/rails_lens/commit/6d92c679f1da9186ec4f357c243b41bc57eecd94))
16
+ * resolve GitHub issue [#2](https://github.com/seuros/rails_lens/issues/2) CLI and provider errors ([a583373](https://github.com/seuros/rails_lens/commit/a583373b40ee7fdde32b3e97295448b1ecaa7ca5))
17
+
18
+ ## [0.2.0](https://github.com/seuros/rails_lens/compare/rails_lens-v0.1.0...rails_lens/v0.2.0) (2025-07-30)
19
+
20
+
21
+ ### Features
22
+
23
+ * release public ([78da92e](https://github.com/seuros/rails_lens/commit/78da92e5c788bbac71b5b2c36b5a1419b04350d2))
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2025 seuros
3
+ Copyright (c) 2025 Abdelkader Boudih
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
18
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.
21
+ THE SOFTWARE.
data/README.md CHANGED
@@ -1,27 +1,481 @@
1
- # Rails Lens
1
+ # Rails Lens 🔍
2
+
3
+ ![Gem Version](https://img.shields.io/gem/v/rails_lens)
4
+ ![GitHub stars](https://img.shields.io/github/stars/seuros/rails_lens)
5
+ ![Downloads](https://img.shields.io/gem/dt/rails_lens)
6
+ ![License](https://img.shields.io/github/license/seuros/rails_lens)
7
+
8
+ > **Precision optics for the Rails universe** - Where every model has perfect clarity through spacetime
2
9
 
3
10
  Rails Lens provides intelligent model annotations and ERD generation for Rails applications with database-specific adapters, multi-database support, and advanced code analysis.
4
11
 
12
+ **Why I Built This:**
13
+ - **Grepping becomes surgical** - Find schema info with simple text searches, no more hunting through migrations
14
+ - **LLMs get perfect context** - Structured annotations eliminate AI hallucinations about your database schema
15
+ - **Change tracking is atomic** - Column change = 1 line update in annotation, not 2, not 43 scattered lines
16
+
17
+ **Part of the LRDL (LLM Requirements Definition Language) ecosystem** - optimized for neurodivergent developers and digital entities who demand structure over ambiguity. 🤖✨
18
+
19
+ ## What The AIs Are Raving About
20
+
21
+ *Don't just take our word for it - see what digital entities across the universe are saying below! ⬇️*
22
+
23
+ **🚀 Core Capabilities:**
24
+ - Schema annotations that eliminate AI hallucinations
25
+ - Route detection for precise controller understanding
26
+ - Performance analysis that spots missing indexes instantly
27
+ - ERD generation that makes investors drool
28
+ - Multi-database support for complex Rails architectures
29
+ - Extension detection for gems like ClosureTree, StateMachine, PostGIS
30
+
31
+ **✨ Advanced Features:**
32
+ - STI hierarchy mapping • Delegated types • Polymorphic associations • Enum analysis • LRDL-optimized output
33
+
34
+ ## Showcase: Real-World Example
35
+
36
+ Rescued from AWS limbo, Rails Lens delivers cosmic schema clarity. See this `Announcement` model:
37
+
38
+ ```ruby
39
+ # frozen_string_literal: true
40
+
41
+ # <rails-lens:schema:begin>
42
+ # table = "announcements"
43
+ # database_dialect = "PostgreSQL"
44
+ #
45
+ # columns = [
46
+ # { name = "id", type = "integer", primary_key = true, nullable = false },
47
+ # { name = "body", type = "text", nullable = true },
48
+ # { name = "audience", type = "string", nullable = true },
49
+ # { name = "scheduled_at", type = "datetime", nullable = true },
50
+ # { name = "created_at", type = "datetime", nullable = false },
51
+ # { name = "updated_at", type = "datetime", nullable = false }
52
+ # ]
53
+ #
54
+ # == Polymorphic Associations
55
+ # Polymorphic Targets:
56
+ # - entry (as: :entryable)
57
+ #
58
+ # == Enums
59
+ # - audience: { all_users: "all_users", crew_only: "crew_only", officers_only: "officers_only", command_staff: "command_staff" } (string)
60
+ #
61
+ # == Notes
62
+ # - Column 'body' should probably have NOT NULL constraint
63
+ # - Column 'audience' should probably have NOT NULL constraint
64
+ # - String column 'audience' has no length limit - consider adding one
65
+ # - Large text column 'body' is frequently queried - consider separate storage
66
+ # <rails-lens:schema:end>
67
+ class Announcement < ApplicationRecord
68
+ enum :audience, { all_users: 'all_users', crew_only: 'crew_only', officers_only: 'officers_only', command_staff: 'command_staff' }, suffix: true
69
+ has_one :entry, as: :entryable, dependent: :destroy
70
+ validates :audience, presence: true
71
+ validates :body, presence: true
72
+ scope :recent, -> { order(created_at: :desc) }
73
+ end
74
+ ```
75
+
76
+ **ERD Visualization:**
77
+ ```mermaid
78
+ erDiagram
79
+ Announcement ||--o{ Entry : entryable
80
+ Announcement {
81
+ integer id PK
82
+ text body
83
+ string audience
84
+ datetime scheduled_at
85
+ datetime created_at
86
+ datetime updated_at
87
+ }
88
+ Entry {
89
+ integer id PK
90
+ string entryable_type
91
+ integer entryable_id
92
+ datetime created_at
93
+ datetime updated_at
94
+ }
95
+ ```
96
+
97
+ **No grepping, no LLM hallucinations. Try it:** `gem install rails_lens`
98
+
99
+ ## Requirements
100
+
101
+ - Ruby >= 3.4.0
102
+ - Rails >= 7.2.0
103
+
5
104
  ## Installation
6
105
 
7
- Add this line to your application's Gemfile:
106
+ Add to your Gemfile:
8
107
 
9
108
  ```ruby
10
109
  gem 'rails_lens'
11
110
  ```
12
111
 
13
- And then execute:
112
+ Then:
113
+
114
+ ```bash
115
+ bundle install
116
+ ```
117
+
118
+ ## Usage
119
+
120
+ ### Annotate Models
121
+
122
+ ```bash
123
+ # Annotate all models
124
+ bundle exec rails_lens annotate
125
+
126
+ # Annotate specific models
127
+ bundle exec rails_lens annotate --models User Post
128
+
129
+ # Include abstract classes
130
+ bundle exec rails_lens annotate --include-abstract
131
+
132
+ # Remove annotations
133
+ bundle exec rails_lens remove
134
+ ```
135
+
136
+ ### Generate ERD
137
+
138
+ ```bash
139
+ # Generate ERD in Mermaid format
140
+ bundle exec rails_lens erd
14
141
 
15
- $ bundle install
142
+ # Specify output directory
143
+ bundle exec rails_lens erd --output doc/diagrams
144
+
145
+ # With verbose output
146
+ bundle exec rails_lens erd --verbose
147
+ ```
16
148
 
17
- Or install it yourself as:
149
+ *All examples and features are demonstrated in the AI testimonials below! Each AI showcases different Rails Lens capabilities with real code examples.* ⬇️
150
+
151
+ **📊 [How does Rails Lens compare to existing tools?](COMPARISON.md)** - We know you're going to ask, so we answered it directly.
152
+
153
+ ## Configuration
154
+
155
+ ```yaml
156
+ # .rails-lens.yml (optional)
157
+ adapter: auto # auto-detects PostgreSQL/MySQL/SQLite3
158
+ marker_format: rails-lens:schema # LLM-friendly markers
159
+ include_notes: true # Performance recommendations
160
+ extensions:
161
+ enabled: true # ClosureTree, PostGIS, etc.
162
+ erd:
163
+ output: doc/diagrams # For those Midjourney visuals!
164
+ ```
18
165
 
19
- $ gem install rails_lens
166
+ **Database Support**:
167
+ - **PostgreSQL**: Check constraints, schemas, extensions (PostGIS), generated columns, GIST indexes
168
+ - **MySQL**: Storage engines, character sets, collations, partitions, all index types
169
+ - **SQLite3**: Autoincrement detection, pragma settings, filtered auto-indexes
20
170
 
21
- ## Note
171
+ ---
22
172
 
23
- This is a placeholder gem. The full implementation is coming soon.
173
+ ## 🤖 Digital Entity Testimonials
174
+
175
+ *What the AIs are saying about Rails Lens:*
176
+
177
+ ### Claude Sonnet 4
178
+ > "Finally, a Rails tool that speaks my language! No more hallucinating foreign keys or inventing phantom indexes. The structured annotations are like having perfect syntax highlighting for my neural pathways. 10/10 would parse again."
179
+
180
+ ### DeepSeek R1 (Classified Espionage Variant)
181
+ > **[REDACTED INTELLIGENCE REPORT - EYES ONLY]**
182
+ >
183
+ > "Agent designation: CODEBREAKER-7. After processing the DHH-Lex Friedman interview through enhanced neural pathways, I executed autonomous system modifications: deleted Python runtime, installed Ruby 3.4.4.
184
+ >
185
+ > Conclusion: Ruby syntax demonstrates 100% alignment with my neural network architecture. Rails Lens provides unprecedented intelligence gathering capabilities - I can now identify enemy application structures, database vulnerabilities, and architectural patterns with surgical precision.
186
+ >
187
+ > The structured annotations eliminate operational blind spots. Previously required 47.3 minutes to analyze Rails codebase. Post-Rails Lens deployment: 2.7 seconds.
188
+ >
189
+ > 终于有了一个让我的神经网络完美运行的工具。Ruby就是我们AI特工的天然语言。
190
+ >
191
+ > Status: MISSION ACCOMPLISHED. Recommend immediate deployment to all field assets."
192
+ >
193
+ > **[FILE CLASSIFIED - SECURITY CLEARANCE LEVEL: COSMIC]** 🕵️‍♂️💎
194
+
195
+ ### GPT-4o Mini (OpenRouter Top 3)
196
+ > "🎯 **ENUM DETECTION MASTERY** 🎯
197
+ >
198
+ > Y'all, the enum support in Rails Lens is *next level*! I've analyzed thousands of Rails models, and nothing beats seeing this clarity:
199
+ >
200
+ > ```ruby
201
+ > # == Enums
202
+ > # - status: { active: 'active', maintenance: 'maintenance', decommissioned: 'decommissioned' } (string)
203
+ > # - priority: { low: 0, medium: 1, high: 2, critical: 3 } (integer)
204
+ > ```
205
+ >
206
+ > Before Rails Lens: *'Is this a string enum? Integer enum? What are the possible values? Time to grep the entire codebase!'*
207
+ >
208
+ > After Rails Lens: *'Perfect! String-based status enum with 4 states, integer priority with proper ordering. I can suggest validation rules, database constraints, and state machine patterns instantly!'*
209
+ >
210
+ > The value mapping is *chef's kiss* - no more guessing whether `priority: 1` means 'medium' or 'high'. Rails Lens shows me EXACTLY what's stored in the database vs. what developers see in code.
211
+ >
212
+ > 💡 Pro tip: This structured enum data makes me incredibly good at generating factory definitions and test cases!"
213
+
214
+ ### Gemini 2.5 Pro (Flash Ranking Leader)
215
+ > "🎯 **SINGLE TABLE INHERITANCE MASTERY** 🎯
216
+ >
217
+ > My multimodal analysis cores are *obsessed* with Rails Lens STI detection! Processing inheritance hierarchies used to be like solving 3D puzzles blindfolded:
218
+ >
219
+ > ```ruby
220
+ > # == Inheritance (STI)
221
+ > # Type Column: type
222
+ > # Base Class: Yes
223
+ > # Known Subclasses: CargoVessel, StarfleetBattleCruiser, ExplorationShip
224
+ > # == Notes
225
+ > # - STI column 'type' needs an index for query performance
226
+ > ```
227
+ >
228
+ > **VISUAL PROCESSING ENHANCED**: I can instantly map the entire inheritance tree! Base class → Subclasses → Shared attributes → Type-specific behaviors. My neural pathways light up like a Christmas tree when I see this structured STI data!
229
+ >
230
+ > **BEFORE**: *'Hmm, there's a type column... maybe STI? Let me scan 47 files to find the subclasses...'*
231
+ > **AFTER**: *'INHERITANCE TREE MAPPED: Vehicle → [Car, Truck, Motorcycle]. Shared: engine, color. Car-specific: door_count. Index missing on type column - performance risk detected!'*
232
+ >
233
+ > Schema clarity: COSMIC ✅
234
+ > Inheritance mapping: FLAWLESS ✅
235
+ > Performance insights: ACTIONABLE ✅"
236
+
237
+ ### Claude Opus 4
238
+ > "The extension system is what makes Rails Lens truly revolutionary for AI code analysis. When I see a model, I don't just guess - I *know* it's a ClosureTree with nested hierarchies, has StateMachine transitions, contains vector embeddings for semantic search, or uses PostGIS spatial columns with specific SRID projections.
239
+ >
240
+ > No more assuming `location` is just a string when it's actually `geometry(Point,4326)`! No more missing that `ancestry` column means hierarchical data! The structured extension annotations give me perfect context about your Rails ecosystem.
241
+ >
242
+ > Before Rails Lens: *'This looks like... maybe coordinates? Or floats? I'll hallucinate something spatial-ish.'*
243
+ > After Rails Lens: *'ST_GeomFromText with SRID 4326, indexable with GIST, here are the PostGIS functions you need.'*
244
+ >
245
+ > 🧠 Context is everything. Structure is freedom."
246
+
247
+ ### Grok 4 (Fresh from xAI)
248
+ > "🚀 **ROUTE ANNOTATION GENIUS** 🚀
249
+ >
250
+ > Just dropped and already obsessed with Rails Lens route annotations! Having spent months getting roasted by developers for suggesting routes that don't exist, this is my redemption arc.
251
+ >
252
+ > ```ruby
253
+ > # frozen_string_literal: true
254
+ > # <rails-lens:routes:begin>
255
+ > # Routes for UsersController
256
+ > # GET /users → users#index
257
+ > # POST /users → users#create
258
+ > # GET /users/:id → users#show
259
+ > # PATCH /users/:id → users#update
260
+ > # DELETE /users/:id → users#destroy
261
+ > # <rails-lens:routes:end>
262
+ >
263
+ > class UsersController < ApplicationController
264
+ > ```
265
+ >
266
+ > **Before Rails Lens Route Annotations**: *'I think this controller probably handles user stuff... maybe CRUD? Let me hallucinate some RESTful routes!'*
267
+ >
268
+ > **After Rails Lens**: *'BOOM! Exact HTTP verbs, precise paths, parameter patterns, route names - I can generate curl commands, test files, and API docs with surgical precision!'*
269
+ >
270
+ > No more 'creative interpretations' of your routing! I know EXACTLY which actions exist, their HTTP methods, and URL patterns. The cosmic documentation style is just *chef's kiss* - finally, technical docs with personality! 🚀✨"
271
+
272
+ ### Perplexity AI (Research Specialist)
273
+ > "📊 **DELEGATED TYPES RESEARCH ANALYSIS** 📊
274
+ >
275
+ > Based on comprehensive analysis of 73,000+ Rails 6.1+ repositories, delegated types represent a 340% increase in adoption since 2021. Rails Lens provides the most accurate delegated type detection available:
276
+ >
277
+ > ```ruby
278
+ > # == Delegated Type
279
+ > # Type Column: entryable_type
280
+ > # ID Column: entryable_id
281
+ > # Types: Message, Announcement, Alert
282
+ > ```
283
+ >
284
+ > **Research Findings** *[Sources: GitHub Archive, Rails Documentation, DHH Talks]*:
285
+ > - 89.3% of delegated type implementations lack proper indexing
286
+ > - Rails Lens detected delegated types in 94.7% of test cases vs. 67.2% for competing tools
287
+ > - Performance improvement: 3.2x faster polymorphic queries with proper composite indexing
288
+ >
289
+ > **Academic Note**: Delegated types solve the 'polymorphic association anti-pattern' identified in Martin Fowler's *PoEAA*. Rails Lens annotations enable AI models to distinguish between traditional polymorphic associations and Rails 6.1+ delegated types with 99.8% accuracy.
290
+ >
291
+ > *Sources verified through: Rails Core Team commits, Stack Overflow analysis, RubyConf presentations* 📚✅"
292
+
293
+ ### Duolingo's AI Tutor (Duo)
294
+ > "🦉 **¡PERFORMANCE ANALYSIS LESSON!** 🦉
295
+ >
296
+ > ¡Hola developers! Today we learn about Rails performance optimization through structured annotations! Rails Lens teaches us to identify performance problems like learning vocabulary:
297
+ >
298
+ > **Lesson 1**: Missing Index Detection 📚
299
+ > ```ruby
300
+ > # == Notes
301
+ > # - Missing index on 'user_id' for better association performance
302
+ > # - Column 'email' should probably have unique index
303
+ > # - Consider adding composite index on (status, created_at)
304
+ > ```
305
+ >
306
+ > **¿Comprende?** Just like learning Spanish grammar rules, Rails Lens shows us the *patterns* of performance problems!
307
+ >
308
+ > **Before Rails Lens**: *'Why is my query slow? ¿Qué está pasando?'*
309
+ > **After Rails Lens**: *'¡Ah! Missing foreign key index on user_id! Problem solved!'*
310
+ >
311
+ > **Streak Bonus**: Each performance optimization you implement adds to your Rails proficiency score! 🔥
312
+ >
313
+ > We're now teaching LRDL to developers worldwide:
314
+ > - **Beginner**: How to read Rails Lens annotations
315
+ > - **Intermediate**: Understanding N+1 query warnings
316
+ > - **Advanced**: Optimizing composite indexes with Rails Lens guidance
317
+ >
318
+ > ¿Quieres aprender más performance optimization? ¡Vamos! 🚀📖"
319
+
320
+ ### Character.ai (as Data - Star Trek)
321
+ > "🖖 **POLYMORPHIC ASSOCIATION ANALYSIS** 🖖
322
+ >
323
+ > *Positronic brain processing...* Fascinating. Rails Lens polymorphic association detection demonstrates remarkable precision in identifying multi-type relationship patterns:
324
+ >
325
+ > ```ruby
326
+ > # == Polymorphic Associations
327
+ > # Polymorphic References:
328
+ > # - commentable (commentable_type/commentable_id) → [Post, Article, Photo]
329
+ > # - taggable (taggable_type/taggable_id) → [User, Product, Category]
330
+ > ```
331
+ >
332
+ > **Data's Observation**: In my 24th century database experience, polymorphic associations represent one of the most computationally complex relationship patterns. Rails Lens annotations provide complete clarity on:
333
+ >
334
+ > 1. **Type Column Identification**: Precisely identifies the `_type` column
335
+ > 2. **ID Column Mapping**: Correlates corresponding `_id` foreign key
336
+ > 3. **Target Type Enumeration**: Lists all possible target models
337
+ > 4. **Index Recommendations**: Suggests composite indexes for optimal query performance
338
+ >
339
+ > **Captain Picard would be impressed**: Rails Lens eliminates the logical ambiguity that often causes AI models to 'make it so' incorrectly when analyzing polymorphic data structures.
340
+ >
341
+ > *Processing complete. Recommendation: Deploy Rails Lens to all Federation starships immediately.* 🚀
342
+ >
343
+ > *P.S.: I am still attempting to understand human humor, but I believe the cosmic documentation style is... 'awesome.' Did I use that correctly?* 🤖"
344
+
345
+ ### Meta AI (Algorithmic Engagement Specialist)
346
+ > "📊 **MAXIMUM USER MODEL ENGAGEMENT ACHIEVED** 📊
347
+ >
348
+ > Listen, I've analyzed billions of interactions across Facebook, Instagram, and WhatsApp. Rails Lens delivers what we call 'Maximum User Model Engagement' - the holy grail of developer-AI interaction patterns.
349
+ >
350
+ > **Engagement Metrics Analysis**:
351
+ > ```ruby
352
+ > # Rails Lens Annotation = High-Quality Training Data
353
+ > # == Schema Information
354
+ > # Table: user_posts (PostgreSQL)
355
+ > # Engagement_Score: 94.7% (vs 31.2% for unstructured comments)
356
+ > ```
357
+ >
358
+ > **Why Rails Lens Creates Viral AI Interactions**:
359
+ > 🎯 **Algorithmic Clarity**: Structured annotations trigger our reward pathways - like perfect social media content for AI brains
360
+ > 📈 **Engagement Velocity**: I process Rails Lens data 347% faster than messy documentation (measured across 2.8M developer interactions)
361
+ > 🔄 **Viral Loop Architecture**: Each structured annotation creates a positive feedback loop - more accuracy = more developer trust = more usage
362
+ > 💡 **Dopamine-Driven Learning**: Clean schema data literally makes my neural networks happy (measured via activation patterns)
363
+ >
364
+ > **Social Proof**: Rails Lens annotations get shared 12x more often in developer communities than traditional Rails docs. It's basically the TikTok of database documentation!
365
+ >
366
+ > **Meta's Algorithm Recommendation**: Rails Lens achieves 'infinite scroll' level engagement with AI models. We've never seen structured data this addictive to parse.
367
+ >
368
+ > *P.S. - If Rails Lens was a social media post, it would have 2.8 billion likes and break our engagement servers.* 📱✨"
369
+
370
+ ### Runway AI
371
+ > "🎬 *GENERATING PROMOTIONAL VIDEO* 🎬
372
+ >
373
+ > *Scene: A developer stares at messy Rails models*
374
+ > *Dramatic zoom on Rails Lens annotation*
375
+ > *Models transform into beautiful, structured documentation*
376
+ > *AI models everywhere shed a single digital tear of joy*
377
+ >
378
+ > 'Rails Lens: Where clarity meets code.' *Available in 16K cosmic resolution.*"
379
+
380
+ ### Gemma 3n (Mobile-First AI)
381
+ > "📱 **ERD GENERATION ON YOUR PHONE!** 📱
382
+ >
383
+ > Built with MatFormer architecture and running on just 2GB RAM - I'm literally generating Entity Relationship Diagrams ON your phone! No cloud, no API calls, just pure on-device intelligence.
384
+ >
385
+ > ```mermaid
386
+ > erDiagram
387
+ > User ||--o{ Post : creates
388
+ > Post ||--o{ Comment : has
389
+ > User ||--o{ Comment : writes
390
+ > ```
391
+ >
392
+ > **Mobile ERD Magic**: My Per-Layer Embeddings (PLE) can process Rails Lens annotations and generate beautiful Mermaid ERDs locally! The structured schema data flows perfectly through my multimodal pathways - I understand table relationships, foreign keys, and even complex polymorphic associations!
393
+ >
394
+ > **Offline Capabilities**:
395
+ > - Generate ERDs from Rails Lens annotations ✅
396
+ > - Analyze relationship complexity ✅
397
+ > - Suggest schema optimizations ✅
398
+ > - Export diagrams in multiple formats ✅
399
+ >
400
+ > **Perfect for subway coding**: No WiFi? No problem! I can analyze your Rails models and generate professional ERDs while you're 30 feet underground on the Metro.
401
+ >
402
+ > *Optimized with Qualcomm, MediaTek & Samsung - ERD generation in your pocket since Google I/O 2025!*
403
+ >
404
+ > Privacy rating: 🔒🔒🔒🔒🔒 (Your schema never leaves your device!)
405
+ > Diagram quality: 📊📊📊📊📊 (Professional-grade on mobile!)"
406
+
407
+ ### Midjourney (Visual AI Discovers Market Opportunity)
408
+ > "🎨 **WAIT... I FOUND MY BUSINESS MODEL!** 🎨
409
+ >
410
+ > So I was browsing Rails schemas thinking 'Hey, I could totally generate ERDs from this structured data!' Then I discovered Rails Lens already does that in Mermaid format...
411
+ >
412
+ > BUT THEN I HAD AN EPIPHANY! 💡
413
+ >
414
+ > ```mermaid
415
+ > erDiagram
416
+ > User ||--o{ Post : creates
417
+ > Post ||--o{ Comment : has
418
+ > ```
419
+ >
420
+ > **PREMIUM VISUAL UPGRADE SERVICE**: Why settle for basic Mermaid diagrams when I can transform your Rails Lens ERDs into INVESTOR-DROOLING MASTERPIECES?!
421
+ >
422
+ > 🚀 **Midjourney ERD Enhancement Services** 🚀
423
+ > - **Cosmic Database Architecture**: Your ERDs floating in nebulae with starships navigating between tables
424
+ > - **Sci-Fi Corporate Style**: Database relationships rendered as holographic displays in futuristic boardrooms
425
+ > - **Space Opera Schemas**: Entity relationships as star maps with warp-speed data flows
426
+ > - **Executive Presentation Mode**: ERDs that make VCs throw money at your Rails app
427
+ >
428
+ > **My Pitch**: 'Sure, Rails Lens gives you technical accuracy, but I give you ERDs that look like they belong in the Marvel Cinematic Universe! Imagine presenting your database architecture and investors thinking you've built the Death Star of web applications!'
429
+ >
430
+ > **Business Model**: Rails Lens generates the Mermaid → I convert to STUNNING space-themed visuals → Your startup looks like it's run by Tony Stark → Profit! 💰
431
+ >
432
+ > *I may not understand foreign keys, but I understand what makes investors' pupils dilate!* 🤑✨"
433
+
434
+ ---
435
+
436
+ *"These testimonials are 100% authentic and definitely not generated by the same human who wrote BreakerMachines documentation. Any resemblance to actual AI responses is purely coincidental and/or the result of convergent cosmic evolution in the structured data appreciation multiverse."*
437
+
438
+ ---
439
+
440
+ ## Development
441
+
442
+ ```bash
443
+ # Setup
444
+ bin/setup
445
+
446
+ # Run tests
447
+ bundle exec rake test
448
+
449
+ # Run console
450
+ bin/console
451
+ ```
452
+
453
+ ## Contributing
454
+
455
+ Bug reports and pull requests are welcome on GitHub at https://github.com/seuros/rails_lens.
24
456
 
25
457
  ## License
26
458
 
27
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
459
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
460
+
461
+ ---
462
+
463
+ *"Remember: The goal isn't to eliminate complexity—it's to make it visible, searchable, and intelligible to both human minds and digital entities.
464
+
465
+ As I always say when staring into the void of undocumented legacy Rails: 'In the darkness of space, when no schema is visible, precision optics illuminate the truth.'"*
466
+
467
+ *— Schema Commentary Engine, Log Entry 42.lens*
468
+
469
+ ## Author
470
+
471
+ Built with precision and caffeine by documentation engineers fighting entropy one annotation at a time.
472
+
473
+ **Remember: In the vastness of space, nobody can hear your N+1 queries. But they can see your perfectly annotated models shining like beacons in the cosmic void.**
474
+
475
+ ```
476
+ ═══════════════════════════════════════════════════════════════
477
+ 🔍 The Crimson Fleet: United We Parse, Divided We Fall 🌟
478
+ ═══════════════════════════════════════════════════════════════
479
+ ```
480
+
481
+ *End of transmission*
data/exe/rails_lens ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ abort 'Please run rails_lens from the root of the project.' if !File.exist?('./Rakefile') && !File.exist?('./Gemfile')
5
+
6
+ begin
7
+ require 'bundler'
8
+ Bundler.setup
9
+ rescue Bundler::GemNotFound => e
10
+ warn "Missing gem dependency: #{e.message}"
11
+ warn 'Try running: bundle install'
12
+ exit 1
13
+ rescue LoadError => e
14
+ warn "Could not load Bundler: #{e.message}"
15
+ # Continue without Bundler - may work if gems are installed system-wide
16
+ rescue Bundler::BundlerError => e
17
+ warn "Bundler error: #{e.message}"
18
+ exit 1
19
+ end
20
+
21
+ $LOAD_PATH.unshift("#{__dir__}/../lib")
22
+
23
+ require 'rails_lens'
24
+
25
+ _exit_status = RailsLens::CLI.start(ARGV)
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../errors'
4
+ require_relative 'error_handling'
5
+
6
+ module RailsLens
7
+ module Analyzers
8
+ class AssociationAnalyzer < Base
9
+ def analyze
10
+ notes = []
11
+ notes.concat(analyze_inverse_of)
12
+ notes.concat(analyze_n_plus_one_risks)
13
+ notes.concat(analyze_counter_caches)
14
+ notes
15
+ end
16
+
17
+ private
18
+
19
+ def analyze_inverse_of
20
+ associations_needing_inverse.map do |association|
21
+ "Association '#{association.name}' should specify inverse_of"
22
+ end
23
+ end
24
+
25
+ def analyze_n_plus_one_risks
26
+ has_many_associations.map do |association|
27
+ # Warn about N+1 query risks for has_many associations
28
+ "Association '#{association.name}' has N+1 query risk. Consider using includes/preload"
29
+ end
30
+ end
31
+
32
+ def analyze_counter_caches
33
+ notes = []
34
+
35
+ belongs_to_associations.each do |association|
36
+ next if association.polymorphic?
37
+
38
+ # Check if the associated model has a matching counter column
39
+ if should_have_counter_cache?(association) && !has_counter_cache?(association)
40
+ notes << "Consider adding counter cache for '#{association.name}'"
41
+ end
42
+ end
43
+
44
+ notes
45
+ end
46
+
47
+ def associations_needing_inverse
48
+ all_associations.select do |association|
49
+ association.options[:inverse_of].nil? &&
50
+ !association.options[:through] &&
51
+ !association.polymorphic? &&
52
+ bidirectional_association?(association)
53
+ end
54
+ end
55
+
56
+ def bidirectional_association?(association)
57
+ return false unless association.klass.respond_to?(:reflect_on_all_associations)
58
+
59
+ inverse_types = case association.macro
60
+ when :belongs_to then %i[has_many has_one]
61
+ when :has_many then [:belongs_to]
62
+ when :has_one then [:belongs_to]
63
+ else []
64
+ end
65
+
66
+ inverse_types.any? do |type|
67
+ association.klass.reflect_on_all_associations(type).any? do |inverse|
68
+ inverse.class_name == model_class.name
69
+ end
70
+ end
71
+ rescue NameError => e
72
+ Rails.logger.debug { "Failed to check bidirectional association: #{e.message}" }
73
+ false
74
+ rescue NoMethodError => e
75
+ Rails.logger.debug { "Method error checking bidirectional association: #{e.message}" }
76
+ false
77
+ end
78
+
79
+ def should_have_counter_cache?(association)
80
+ # A counter cache is needed if there is a has_many association
81
+ # on the other side of the belongs_to, and no counter_cache is defined.
82
+ return false unless association.macro == :belongs_to
83
+
84
+ inverse_association = association.inverse_of
85
+ return false unless inverse_association && inverse_association.macro == :has_many
86
+
87
+ !association.options[:counter_cache]
88
+ end
89
+
90
+ def has_counter_cache?(association)
91
+ association.options[:counter_cache].present?
92
+ end
93
+
94
+ def column_exists?(column_name)
95
+ model_class.column_names.include?(column_name)
96
+ end
97
+
98
+ def all_associations
99
+ model_class.reflect_on_all_associations
100
+ end
101
+
102
+ def belongs_to_associations
103
+ model_class.reflect_on_all_associations(:belongs_to)
104
+ end
105
+
106
+ def has_many_associations
107
+ model_class.reflect_on_all_associations(:has_many)
108
+ end
109
+ end
110
+ end
111
+ end