support_table_data 1.4.0 → 1.5.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/AGENTS.md +140 -0
  3. data/ARCHITECTURE.md +538 -0
  4. data/CHANGELOG.md +13 -0
  5. data/README.md +50 -5
  6. data/VERSION +1 -1
  7. data/lib/support_table_data/documentation/source_file.rb +95 -0
  8. data/lib/support_table_data/documentation/yard_doc.rb +91 -0
  9. data/lib/support_table_data/documentation.rb +9 -0
  10. data/lib/support_table_data/railtie.rb +22 -1
  11. data/lib/support_table_data/validation_error.rb +16 -0
  12. data/lib/support_table_data.rb +71 -53
  13. data/lib/tasks/support_table_data.rake +55 -12
  14. data/lib/tasks/utils.rb +63 -0
  15. data/support_table_data.gemspec +1 -1
  16. data/test_app/.gitignore +4 -0
  17. data/test_app/Gemfile +7 -0
  18. data/test_app/Rakefile +6 -0
  19. data/test_app/app/models/application_record.rb +5 -0
  20. data/test_app/app/models/secondary_application_record.rb +7 -0
  21. data/test_app/app/models/status.rb +11 -0
  22. data/test_app/app/models/thing.rb +10 -0
  23. data/test_app/bin/rails +4 -0
  24. data/test_app/config/application.rb +42 -0
  25. data/test_app/config/boot.rb +3 -0
  26. data/test_app/config/database.yml +17 -0
  27. data/test_app/config/environment.rb +5 -0
  28. data/test_app/config/environments/development.rb +11 -0
  29. data/test_app/config/environments/test.rb +11 -0
  30. data/test_app/config.ru +6 -0
  31. data/test_app/db/migrate/20260103060951_create_status.rb +8 -0
  32. data/test_app/db/schema.rb +20 -0
  33. data/test_app/db/secondary_migrate/20260104000001_create_things.rb +7 -0
  34. data/test_app/db/secondary_schema.rb +25 -0
  35. data/test_app/db/support_tables/statuses.yml +19 -0
  36. data/test_app/db/support_tables/things.yml +5 -0
  37. data/test_app/lib/tasks/database.rake +11 -0
  38. data/test_app/log/.keep +0 -0
  39. metadata +34 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 57189f00e55af0f6d3476edbe8921bfb7ba341fa9a1c6e51eb0674e66327bd12
4
- data.tar.gz: f80d9a8f7ce4877aec13c5f0151ddc017bbcb94ea4b85b2c404b23161d11aaf8
3
+ metadata.gz: 7fded73fcb55268fa76b155b9cb192667bbe535e4e11f0cf00f8c3b8536fe3ee
4
+ data.tar.gz: 9e06e50abcba73a18918a7fe8fa0168c93a2d0b39c0d1cfa03f1d512368632af
5
5
  SHA512:
6
- metadata.gz: df96d9b761bb03c2ddc9bc915bc5441c24f8bf06e20f53fb2d962ae74c19f6828f84f3b4c3f5c1fe6766bceed05c4e64ec6ae458c64c9e6bf549855b4a492222
7
- data.tar.gz: 820ebdea69220e6a03c5b0966138285af9c7e3181c73532917d074c392cc0a708d5bb4c67d0d11f937ef0ffd81e828f226f64aa0a632ec7475578d8edc2a53d6
6
+ metadata.gz: c107aa8e78cfbdfe8fdafd1cc42bf2f25b90075f561e9a7933e643ec2773647f4f96cc047d4ed0b90f8b15cd50ffa1e1f282c7f3abc61e25d70c3fb5150a2958
7
+ data.tar.gz: 612b88d848c4eb101018bf2c643f8b76825e7bb22b459a6b5998a70238f9eb8627bbe7f6d8533b362b99300dcdce3a905bc3a22ca30c680ca03e4043c8837c7c
data/AGENTS.md ADDED
@@ -0,0 +1,140 @@
1
+ # Copilot Instructions for support_table_data
2
+
3
+ ## Project Overview
4
+
5
+ A Ruby gem providing an ActiveRecord mixin for managing support/lookup tables with canonical data defined in YAML/JSON/CSV files. The gem dynamically generates helper methods to reference specific records naturally in code (e.g., `Status.pending` instead of `Status.find_by(name: 'Pending')`).
6
+
7
+ **Core concept**: Support tables blur the line between data and code—they contain small canonical datasets that must exist for the application to work.
8
+
9
+ ## Architecture
10
+
11
+ ### Key Components
12
+
13
+ - **`SupportTableData` module** ([lib/support_table_data.rb](lib/support_table_data.rb)): Main concern mixed into ActiveRecord models
14
+ - **Named instance system**: Dynamically generates class methods (`.pending`), predicate methods (`.pending?`), and attribute helpers (`.pending_id`) from hash-based data files
15
+ - **Data sync engine**: Compares canonical data files with database records, creating/updating as needed in atomic transactions
16
+ - **File parsers**: Supports YAML, JSON, and CSV formats with unified interface
17
+
18
+ ### Data Flow
19
+
20
+ 1. Data files (YAML/JSON/CSV) define canonical records with unique key attributes
21
+ 2. `add_support_table_data` registers file paths and triggers method generation for hash-based files
22
+ 3. `sync_table_data!` parses files, loads matching DB records, and updates/creates within transactions
23
+ 4. Named instance methods are dynamically defined via `class_eval` with memoization
24
+
25
+ ## Development Workflows
26
+
27
+ ### Running Tests
28
+
29
+ ```bash
30
+ bundle exec rspec # Run all specs
31
+ bundle exec rspec spec/support_table_data_spec.rb # Single file
32
+ bundle exec rake appraisals # Test against all ActiveRecord versions
33
+ ```
34
+
35
+ Uses RSpec with in-memory SQLite database. Test models defined in [spec/models.rb](spec/models.rb), data files in `spec/data/`.
36
+
37
+ ### Testing Against Multiple ActiveRecord Versions
38
+
39
+ The gem supports ActiveRecord 6.0-8.0. Uses Appraisal for multi-version testing:
40
+
41
+ ```bash
42
+ bundle exec appraisal install # Install all gemfiles
43
+ bundle exec appraisal rspec # Run specs against all versions
44
+ ```
45
+
46
+ See `Appraisals` file and `gemfiles/` directory.
47
+
48
+ ### Code Style
49
+
50
+ Uses Standard Ruby formatter:
51
+
52
+ ```bash
53
+ bundle exec rake standard:fix # Auto-fix style issues
54
+ ```
55
+
56
+ ## Critical Patterns
57
+
58
+ ### Named Instance Method Generation
59
+
60
+ **Hash-based data files** trigger dynamic method generation. Example from [spec/data/colors/named_colors.yml](spec/data/colors/named_colors.yml):
61
+
62
+ ```yaml
63
+ red:
64
+ id: 1
65
+ name: Red
66
+ value: 16711680
67
+ ```
68
+
69
+ Generates:
70
+ - `Color.red` → finds record by id
71
+ - `color_instance.red?` → tests if `color_instance.id == 1`
72
+ - `Color.red_id` → returns `1` (if `named_instance_attribute_helpers :id` defined)
73
+
74
+ **Implementation**: See `define_support_table_named_instance_methods` in [lib/support_table_data.rb](lib/support_table_data.rb#L230-L265). Methods are generated using `class_eval` with string interpolation.
75
+
76
+ ### Custom Setters for Associations
77
+
78
+ Support tables often reference other support tables via named instances. Pattern from [spec/models.rb](spec/models.rb#L72-L74):
79
+
80
+ ```ruby
81
+ def group_name=(value)
82
+ self.group = Group.named_instance(value)
83
+ end
84
+ ```
85
+
86
+ Allows data files to reference related records by instance name instead of foreign keys.
87
+
88
+ ### Key Attribute Configuration
89
+
90
+ By default, uses model's `id` column. Override for non-id keys:
91
+
92
+ ```ruby
93
+ self.support_table_key_attribute = :name # Use 'name' instead of 'id'
94
+ ```
95
+
96
+ Key attributes cannot be updated—changing them creates new records.
97
+
98
+ ### Dependency Resolution
99
+
100
+ `sync_all!` automatically resolves dependencies via `belongs_to` associations and loads tables in correct order. For complex cases (join tables, indirect dependencies), explicitly declare:
101
+
102
+ ```ruby
103
+ support_table_dependency "OtherModel"
104
+ ```
105
+
106
+ See [lib/support_table_data.rb](lib/support_table_data.rb#L219-L222) and dependency resolution logic.
107
+
108
+ ## Testing Conventions
109
+
110
+ - **Test data isolation**: Each test deletes all records in `before` block ([spec/spec_helper.rb](spec/spec_helper.rb))
111
+ - **Sync before assertions**: Tests call `sync_table_data!` or `sync_all!` before verifying records exist
112
+ - **Multi-file merging**: Tests verify that multiple data files for same model merge correctly (see `Color` model with 5 data files)
113
+ - **STI handling**: See `Polygon`/`Triangle`/`Rectangle` tests for Single Table Inheritance patterns
114
+
115
+ ## Common Pitfalls
116
+
117
+ 1. **Method name conflicts**: Named instance methods raise `ArgumentError` if method already exists. Instance names must match `/\A[a-z][a-z0-9_]+\z/`
118
+ 2. **Array vs hash data**: Only hash-keyed data generates named instance methods. Use arrays or underscore-prefixed keys (`_others`) for records without helpers
119
+ 3. **Protected instances**: Records in data files cannot be deleted via `destroy` (though this gem doesn't enforce it—see companion caching gem)
120
+ 4. **Transaction safety**: All sync operations wrapped in transactions; changes rollback on failure
121
+
122
+ ## Rails Integration
123
+
124
+ In Rails apps, the gem automatically:
125
+ - Sets `SupportTableData.data_directory` to `Rails.root/db/support_tables`
126
+ - Provides `rake support_table_data:sync` task ([lib/tasks/support_table_data.rake](lib/tasks/support_table_data.rake))
127
+ - Handles eager loading in both classic and Zeitwerk autoloaders
128
+
129
+ ## File References
130
+
131
+ - Main module: [lib/support_table_data.rb](lib/support_table_data.rb)
132
+ - Test models: [spec/models.rb](spec/models.rb) - comprehensive examples of patterns
133
+ - Sync task: [lib/tasks/support_table_data.rake](lib/tasks/support_table_data.rake)
134
+ - Architecture docs: [ARCHITECTURE.md](ARCHITECTURE.md) - detailed diagrams and design decisions
135
+
136
+ ## Version Compatibility
137
+
138
+ - Ruby ≥ 2.5
139
+ - ActiveRecord ≥ 6.0
140
+ - Ruby 3.4+: Requires `csv` gem in Gemfile (removed from stdlib)
data/ARCHITECTURE.md ADDED
@@ -0,0 +1,538 @@
1
+ # Support Table Data Architecture
2
+
3
+ This document describes the architecture and design patterns of the `support_table_data` gem, which provides a robust solution for managing static support tables (lookup tables) in ActiveRecord applications.
4
+
5
+ ## Overview
6
+
7
+ The SupportTableData gem solves the common problem of managing small, canonical datasets that exist at the intersection of data and code. These support tables contain a limited number of rows with values that are often referenced in application logic, making them critical for proper application function.
8
+
9
+ ## Core Components
10
+
11
+ ### Main Components Overview
12
+
13
+ ```mermaid
14
+ flowchart TB
15
+ subgraph "Application Layer"
16
+ Model[ActiveRecord Model]
17
+ DataFiles[Data Files<br/>YAML/JSON/CSV]
18
+ end
19
+
20
+ subgraph "SupportTableData Gem"
21
+ Concern[SupportTableData Module]
22
+ Parser[File Parser]
23
+ Sync[Data Synchronizer]
24
+ Helpers[Helper Methods]
25
+ end
26
+
27
+ subgraph "Infrastructure"
28
+ DB[(Database)]
29
+ Rails[Rails Environment]
30
+ Rake[Rake Tasks]
31
+ end
32
+
33
+ Model --> Concern
34
+ DataFiles --> Parser
35
+ Parser --> Sync
36
+ Sync --> DB
37
+ Concern --> Helpers
38
+ Rails --> Rake
39
+ Rake --> Sync
40
+
41
+ style Concern fill:#e1f5fe
42
+ style DataFiles fill:#f3e5f5
43
+ style DB fill:#e8f5e8
44
+ ```
45
+
46
+ ## Data Flow Architecture
47
+
48
+ The gem follows a clear data flow pattern from static files to database records:
49
+
50
+ ```mermaid
51
+ flowchart LR
52
+ subgraph "Source Data"
53
+ YML[YAML Files]
54
+ JSON[JSON Files]
55
+ CSV[CSV Files]
56
+ end
57
+
58
+ subgraph "Processing"
59
+ Parse[File Parser]
60
+ Validate[Data Validation]
61
+ Transform[Data Transformation]
62
+ end
63
+
64
+ subgraph "Storage"
65
+ Memory[In-Memory Cache]
66
+ DB[(Database Tables)]
67
+ end
68
+
69
+ subgraph "Usage"
70
+ Helpers[Helper Methods]
71
+ Queries[Database Queries]
72
+ Predicates[Predicate Methods]
73
+ end
74
+
75
+ YML --> Parse
76
+ JSON --> Parse
77
+ CSV --> Parse
78
+ Parse --> Validate
79
+ Validate --> Transform
80
+ Transform --> Memory
81
+ Transform --> DB
82
+ Memory --> Helpers
83
+ DB --> Queries
84
+ Helpers --> Predicates
85
+
86
+ style Parse fill:#fff3e0
87
+ style DB fill:#e8f5e8
88
+ style Helpers fill:#e3f2fd
89
+ ```
90
+
91
+ ## Class Structure
92
+
93
+ ### Core Module Design
94
+
95
+ ```mermaid
96
+ classDiagram
97
+ class SupportTableData {
98
+ +data_directory : String
99
+ +sync_all!() : Hash
100
+ +support_table_classes() : Array
101
+ }
102
+
103
+ class ActiveRecord_Model {
104
+ +support_table_key_attribute : String
105
+ +support_table_data_directory : String
106
+ +add_support_table_data(path)
107
+ +sync_table_data!() : Array
108
+ +named_instance(name) : Record
109
+ +instance_names() : Array
110
+ +protected_instance?(record) : Boolean
111
+ }
112
+
113
+ class NamedInstanceHelpers {
114
+ +class_name() : Record
115
+ +class_name_question() : Boolean
116
+ +class_name_attribute() : Value
117
+ }
118
+
119
+ class FileParser {
120
+ +parse_yaml(content) : Hash
121
+ +parse_json(content) : Hash
122
+ +parse_csv(content) : Array
123
+ }
124
+
125
+ class DataSynchronizer {
126
+ +sync_records(data) : Array
127
+ +create_record(attributes) : Record
128
+ +update_record(record, attributes) : Record
129
+ }
130
+
131
+ SupportTableData --> ActiveRecord_Model : extends
132
+ ActiveRecord_Model --> NamedInstanceHelpers : generates
133
+ ActiveRecord_Model --> FileParser : uses
134
+ ActiveRecord_Model --> DataSynchronizer : uses
135
+
136
+ note for NamedInstanceHelpers "Methods are dynamically generated based on data file content"
137
+ ```
138
+
139
+ ## Named Instance System
140
+
141
+ The gem's most powerful feature is its named instance system, which generates helper methods from data files:
142
+
143
+ ```mermaid
144
+ flowchart TD
145
+ subgraph "Data File Structure"
146
+ HashData[Hash-based Data]
147
+ ArrayData[Array-based Data]
148
+ end
149
+
150
+ subgraph "Method Generation"
151
+ ClassMethods[Class Methods<br/>Status.pending]
152
+ InstanceMethods[Instance Methods<br/>status.pending?]
153
+ AttributeHelpers[Attribute Helpers<br/>Status.pending_id]
154
+ end
155
+
156
+ subgraph "Runtime Usage"
157
+ FindRecord[Find Specific Record]
158
+ TestRecord[Test Record Type]
159
+ GetAttribute[Get Static Attribute]
160
+ end
161
+
162
+ HashData --> ClassMethods
163
+ HashData --> InstanceMethods
164
+ ArrayData --> ClassMethods
165
+ ClassMethods --> FindRecord
166
+ InstanceMethods --> TestRecord
167
+ AttributeHelpers --> GetAttribute
168
+
169
+ style HashData fill:#f3e5f5
170
+ style ClassMethods fill:#e3f2fd
171
+ style InstanceMethods fill:#e8f5e8
172
+ ```
173
+
174
+ ## Data Synchronization Process
175
+
176
+ The synchronization process ensures database consistency with data files:
177
+
178
+ ```mermaid
179
+ sequenceDiagram
180
+ participant App as Application
181
+ participant Model as AR Model
182
+ participant Parser as File Parser
183
+ participant DB as Database
184
+
185
+ App->>Model: sync_table_data!
186
+ Model->>Parser: Parse data files
187
+ Parser-->>Model: Canonical data
188
+
189
+ Model->>DB: BEGIN TRANSACTION
190
+ Model->>DB: Find existing records
191
+ DB-->>Model: Current records
192
+
193
+ loop For each record
194
+ Model->>Model: Compare attributes
195
+ alt Record changed
196
+ Model->>DB: UPDATE record
197
+ end
198
+ end
199
+
200
+ loop For new records
201
+ Model->>DB: INSERT record
202
+ end
203
+
204
+ Model->>DB: COMMIT TRANSACTION
205
+ Model-->>App: Changes summary
206
+ ```
207
+
208
+ ## File Format Support
209
+
210
+ The gem supports multiple data file formats with a unified interface:
211
+
212
+ ```mermaid
213
+ flowchart LR
214
+ subgraph "Input Formats"
215
+ YAML[YAML<br/>*.yml, *.yaml]
216
+ JSON[JSON<br/>*.json]
217
+ CSV[CSV<br/>*.csv]
218
+ end
219
+
220
+ subgraph "Parser Layer"
221
+ YAMLParser[YAML::safe_load]
222
+ JSONParser[JSON::parse]
223
+ CSVParser[CSV Parser<br/>with headers]
224
+ end
225
+
226
+ subgraph "Output Format"
227
+ Hash[Hash Structure<br/>Named instances]
228
+ Array[Array Structure<br/>Simple records]
229
+ end
230
+
231
+ YAML --> YAMLParser
232
+ JSON --> JSONParser
233
+ CSV --> CSVParser
234
+
235
+ YAMLParser --> Hash
236
+ YAMLParser --> Array
237
+ JSONParser --> Hash
238
+ JSONParser --> Array
239
+ CSVParser --> Array
240
+
241
+ style YAML fill:#e8f5e8
242
+ style JSON fill:#fff3e0
243
+ style CSV fill:#f3e5f5
244
+ ```
245
+
246
+ ## Dependency Resolution
247
+
248
+ The gem automatically resolves dependencies between support table models:
249
+
250
+ ```mermaid
251
+ flowchart TB
252
+ subgraph "Dependency Analysis"
253
+ Belongs[belongs_to Associations]
254
+ Explicit[Explicit Dependencies]
255
+ Through[has_many :through]
256
+ end
257
+
258
+ subgraph "Resolution Strategy"
259
+ Detect[Detect Dependencies]
260
+ Sort[Topological Sort]
261
+ Validate[Circular Detection]
262
+ end
263
+
264
+ subgraph "Load Order"
265
+ Level1[Independent Models]
266
+ Level2[Models with Dependencies]
267
+ Level3[Join Table Models]
268
+ end
269
+
270
+ Belongs --> Detect
271
+ Explicit --> Detect
272
+ Through --> Detect
273
+
274
+ Detect --> Sort
275
+ Sort --> Validate
276
+ Validate --> Level1
277
+ Level1 --> Level2
278
+ Level2 --> Level3
279
+
280
+ style Detect fill:#e3f2fd
281
+ style Sort fill:#f3e5f5
282
+ style Level1 fill:#e8f5e8
283
+ ```
284
+
285
+ ## Rails Integration
286
+
287
+ The gem integrates seamlessly with Rails applications:
288
+
289
+ ```mermaid
290
+ flowchart TD
291
+ subgraph "Rails Boot Process"
292
+ Boot[Application Boot]
293
+ Eager[Eager Loading]
294
+ Routes[Routes Loading]
295
+ end
296
+
297
+ subgraph "Gem Integration"
298
+ Railtie[SupportTableData::Railtie]
299
+ Tasks[Rake Tasks]
300
+ AutoLoad[Auto Discovery]
301
+ end
302
+
303
+ subgraph "Development Workflow"
304
+ Migrate[db:migrate]
305
+ Sync[support_table_data:sync]
306
+ Test[Test Suite Setup]
307
+ end
308
+
309
+ Boot --> Railtie
310
+ Eager --> AutoLoad
311
+ Railtie --> Tasks
312
+ Tasks --> Sync
313
+ Migrate --> Sync
314
+ Sync --> Test
315
+
316
+ style Railtie fill:#e3f2fd
317
+ style Sync fill:#e8f5e8
318
+ style Test fill:#fff3e0
319
+ ```
320
+
321
+ ## Error Handling and Validation
322
+
323
+ The gem includes comprehensive error handling:
324
+
325
+ ```mermaid
326
+ flowchart TD
327
+ subgraph "Validation Points"
328
+ FileFormat[File Format Validation]
329
+ DataStructure[Data Structure Validation]
330
+ MethodNames[Method Name Validation]
331
+ KeyAttributes[Key Attribute Validation]
332
+ end
333
+
334
+ subgraph "Error Types"
335
+ ParseError[File Parse Errors]
336
+ NameError[Method Name Conflicts]
337
+ DataError[Data Consistency Errors]
338
+ TransactionError[Database Transaction Errors]
339
+ end
340
+
341
+ subgraph "Recovery Strategies"
342
+ Rollback[Transaction Rollback]
343
+ ErrorReport[Detailed Error Messages]
344
+ PartialSync[Skip Invalid Records]
345
+ end
346
+
347
+ FileFormat --> ParseError
348
+ DataStructure --> DataError
349
+ MethodNames --> NameError
350
+ KeyAttributes --> DataError
351
+
352
+ ParseError --> ErrorReport
353
+ NameError --> ErrorReport
354
+ DataError --> Rollback
355
+ TransactionError --> Rollback
356
+
357
+ style ParseError fill:#ffebee
358
+ style Rollback fill:#e8f5e8
359
+ style ErrorReport fill:#fff3e0
360
+ ```
361
+
362
+ ## Performance Considerations
363
+
364
+ The gem is designed for optimal performance with small datasets:
365
+
366
+ ```mermaid
367
+ flowchart LR
368
+ subgraph "Optimization Strategies"
369
+ SmallData[Small Dataset Focus<br/>&lt; 100 records]
370
+ Memoization[Method Memoization]
371
+ Transaction[Atomic Transactions]
372
+ LazyLoad[Lazy Method Generation]
373
+ end
374
+
375
+ subgraph "Memory Management"
376
+ ClassVars[Class Variables]
377
+ Mutex[Thread Safety]
378
+ WeakRef[Weak References]
379
+ end
380
+
381
+ subgraph "Database Efficiency"
382
+ BulkOps[Bulk Operations]
383
+ IndexHints[Key Attribute Indexing]
384
+ MinQueries[Minimize Queries]
385
+ end
386
+
387
+ SmallData --> ClassVars
388
+ Memoization --> Mutex
389
+ Transaction --> BulkOps
390
+ LazyLoad --> WeakRef
391
+
392
+ ClassVars --> MinQueries
393
+ Mutex --> IndexHints
394
+ BulkOps --> MinQueries
395
+
396
+ style SmallData fill:#e8f5e8
397
+ style Transaction fill:#e3f2fd
398
+ style MinQueries fill:#fff3e0
399
+ ```
400
+
401
+ ## Extension Points
402
+
403
+ The gem provides several extension points for customization:
404
+
405
+ ```mermaid
406
+ flowchart TB
407
+ subgraph "Customization Options"
408
+ KeyAttr[Custom Key Attributes]
409
+ DataDir[Custom Data Directories]
410
+ Parser[Custom File Parsers]
411
+ Validation[Custom Validations]
412
+ end
413
+
414
+ subgraph "Integration Hooks"
415
+ BeforeSync[Before Sync Callbacks]
416
+ AfterSync[After Sync Callbacks]
417
+ MethodGen[Method Generation Hooks]
418
+ ErrorHook[Error Handling Hooks]
419
+ end
420
+
421
+ subgraph "External Gems"
422
+ Cache[SupportTableCache]
423
+ Observers[ActiveRecord Observers]
424
+ Auditing[Auditing Gems]
425
+ end
426
+
427
+ KeyAttr --> BeforeSync
428
+ DataDir --> MethodGen
429
+ Parser --> ErrorHook
430
+ Validation --> AfterSync
431
+
432
+ BeforeSync --> Cache
433
+ MethodGen --> Observers
434
+ ErrorHook --> Auditing
435
+
436
+ style Cache fill:#e3f2fd
437
+ style BeforeSync fill:#f3e5f5
438
+ style MethodGen fill:#e8f5e8
439
+ ```
440
+
441
+ ## Deployment Strategy
442
+
443
+ The gem follows a deployment-friendly pattern:
444
+
445
+ ```mermaid
446
+ flowchart LR
447
+ subgraph "Development"
448
+ DevData[Dev Data Files]
449
+ DevDB[Dev Database]
450
+ DevTest[Test Suite]
451
+ end
452
+
453
+ subgraph "CI/CD Pipeline"
454
+ Build[Build Process]
455
+ Migration[Run Migrations]
456
+ DataSync[Sync Support Data]
457
+ TestRun[Run Tests]
458
+ end
459
+
460
+ subgraph "Production"
461
+ ProdDB[Production Database]
462
+ ProdData[Production Data]
463
+ Monitor[Monitoring]
464
+ end
465
+
466
+ DevData --> Build
467
+ DevDB --> Migration
468
+ DevTest --> TestRun
469
+
470
+ Build --> Migration
471
+ Migration --> DataSync
472
+ DataSync --> TestRun
473
+ TestRun --> ProdDB
474
+
475
+ ProdDB --> ProdData
476
+ ProdData --> Monitor
477
+
478
+ style DataSync fill:#e8f5e8
479
+ style TestRun fill:#e3f2fd
480
+ style Monitor fill:#fff3e0
481
+ ```
482
+
483
+ ## Best Practices
484
+
485
+ ### Model Organization
486
+
487
+ ```mermaid
488
+ flowchart TD
489
+ subgraph "File Structure"
490
+ Models[app/models/]
491
+ DataFiles[db/support_tables/]
492
+ Tests[spec/models/]
493
+ end
494
+
495
+ subgraph "Naming Conventions"
496
+ ModelFile[status.rb]
497
+ DataFile[statuses.yml]
498
+ TestFile[status_spec.rb]
499
+ end
500
+
501
+ subgraph "Content Organization"
502
+ Includes[Include SupportTableData]
503
+ Config[Configure Directories]
504
+ AddData[Add Data Files]
505
+ Helpers[Define Helpers]
506
+ end
507
+
508
+ Models --> ModelFile
509
+ DataFiles --> DataFile
510
+ Tests --> TestFile
511
+
512
+ ModelFile --> Includes
513
+ DataFile --> Config
514
+ TestFile --> AddData
515
+ Config --> Helpers
516
+
517
+ style ModelFile fill:#e3f2fd
518
+ style DataFile fill:#f3e5f5
519
+ style Includes fill:#e8f5e8
520
+ ```
521
+
522
+ ## Summary
523
+
524
+ The SupportTableData gem provides a comprehensive solution for managing static support tables through:
525
+
526
+ 1. **Declarative Configuration**: Define support data in version-controlled files
527
+ 2. **Automatic Synchronization**: Keep database records in sync with data files
528
+ 3. **Generated Helper Methods**: Clean, readable code for accessing specific records
529
+ 4. **Dependency Management**: Automatic resolution of inter-table dependencies
530
+ 5. **Rails Integration**: Seamless integration with Rails applications and deployment workflows
531
+ 6. **Type Safety**: Compile-time method generation with runtime validation
532
+ 7. **Performance**: Optimized for small datasets with minimal overhead
533
+
534
+ The architecture promotes maintainable code by keeping support data close to the application logic while ensuring data consistency across environments.
535
+
536
+ <function_calls>
537
+ <invoke name="get-syntax-docs-mermaid">
538
+ <parameter name="file">flowchart.md
data/CHANGELOG.md CHANGED
@@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## 1.5.0
8
+
9
+ ### Added
10
+
11
+ - The default data directory in a Rails application can be set with the `config.support_table.data_directory` option in the Rails application configuration.
12
+ - Added rake task `support_table_data:yard_docs:add` for Rails applications that will add YARD documentation to support table models for the named instance helpers. There is also a task `support_table_data:yard_docs:verify` that can be used in a build pipeline to verify that the documentation is up to date. You can also remove the documentation with the `support_table_data:yard_docs:remove` task.
13
+ - The data synchronization task is now automatically attached to several Rails tasks: `db:seed`, `db:seed:replant`, `db:prepare`, `db:test:prepare`, `db:fixtures:load`. Support tables will be synced after running any of these tasks. This can be disabled by setting `config.support_table.auto_sync = false` in the Rails application configuration.
14
+
15
+ ### Changed
16
+
17
+ - The default data directory is now set in a Railtie and can be overridden with the `config.support_table.data_directory` option in the Rails application configuration.
18
+ - The `support_table_key_attribute` method now returns "id" if not explicitly set instead of implicitly interpreting `nil` as the primary key. This makes the behavior more consistent and explicit and avoids edge cases when running the code in environments where the database connection is not available. This is a breaking change if the table uses a primary key other than "id" and the `support_table_key_attribute` was not explicitly set to that primary key.
19
+
7
20
  ## 1.4.0
8
21
 
9
22
  ### Fixed