support_table_data 1.4.0 → 1.5.1
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 +4 -4
- data/ARCHITECTURE.md +538 -0
- data/CHANGELOG.md +21 -0
- data/README.md +52 -5
- data/VERSION +1 -1
- data/lib/support_table_data/documentation/source_file.rb +98 -0
- data/lib/support_table_data/documentation/yard_doc.rb +91 -0
- data/lib/support_table_data/documentation.rb +9 -0
- data/lib/support_table_data/railtie.rb +22 -1
- data/lib/support_table_data/validation_error.rb +16 -0
- data/lib/support_table_data.rb +71 -53
- data/lib/tasks/support_table_data.rake +61 -12
- data/lib/tasks/utils.rb +71 -0
- data/support_table_data.gemspec +2 -1
- data/test_app/.gitignore +4 -0
- data/test_app/Gemfile +7 -0
- data/test_app/Rakefile +6 -0
- data/test_app/app/models/application_record.rb +5 -0
- data/test_app/app/models/secondary_application_record.rb +7 -0
- data/test_app/app/models/status.rb +120 -0
- data/test_app/app/models/thing.rb +10 -0
- data/test_app/bin/rails +4 -0
- data/test_app/config/application.rb +42 -0
- data/test_app/config/boot.rb +3 -0
- data/test_app/config/database.yml +17 -0
- data/test_app/config/environment.rb +5 -0
- data/test_app/config/environments/development.rb +11 -0
- data/test_app/config/environments/test.rb +11 -0
- data/test_app/config.ru +6 -0
- data/test_app/db/migrate/20260103060951_create_status.rb +8 -0
- data/test_app/db/schema.rb +20 -0
- data/test_app/db/secondary_migrate/20260104000001_create_things.rb +7 -0
- data/test_app/db/secondary_schema.rb +25 -0
- data/test_app/db/support_tables/statuses.yml +19 -0
- data/test_app/db/support_tables/things.yml +5 -0
- data/test_app/lib/tasks/database.rake +11 -0
- data/test_app/log/.keep +0 -0
- metadata +33 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '081b2612659ea90591ecf5fd7386acbb9d10dbd90c20301e12fba39d3d81e4b3'
|
|
4
|
+
data.tar.gz: b7d4960153f4799031127c8e2fb6ffaa5da49acc1e59833b64c9f417dd9d77df
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e38a2f56f37888a737c8493ec0078666cf8a138415326946829c506a57fc81f5bc3e8407232e7bacbd82a5d0066d9513dd14340360e9d4179a3b1d51a7d69517
|
|
7
|
+
data.tar.gz: 569bbabe38749923686c5d9aa757851f6ba3fad64317f18e3fdb209aec9c714ed1f020a6c07a1588464d1ed9c129bb983ae25d5378ae324b0abee8e467e0fa96
|
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/>< 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,27 @@ 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.1
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- YARD documentation tasks can now take an optional file path argument to add, verify, or remove documentation for a specific support table model instead of all models. For example, you can run `bundle exec rake support_table_data:yard_docs:add[app/models/color.rb]` to add documentation for the `Color` model.
|
|
12
|
+
- Added comment in generated YARD documentation indicating the command to run to update them so that it's clear to users how to keep the documentation up to date.
|
|
13
|
+
- Aliased `support_table_data:yard_docs` to `support_table_data:yard_docs:add` for convenience since adding the documentation is the most common action.
|
|
14
|
+
|
|
15
|
+
## 1.5.0
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- The default data directory in a Rails application can be set with the `config.support_table.data_directory` option in the Rails application configuration.
|
|
20
|
+
- 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.
|
|
21
|
+
- 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.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- 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.
|
|
26
|
+
- 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.
|
|
27
|
+
|
|
7
28
|
## 1.4.0
|
|
8
29
|
|
|
9
30
|
### Fixed
|
data/README.md
CHANGED
|
@@ -8,6 +8,19 @@ This gem provides a mixin for ActiveRecord support table models that allows you
|
|
|
8
8
|
|
|
9
9
|
These kinds of models blur the line between data and code. You'll often end up with constants and application logic based on specific values that need to exist in the table. By using this gem, you can easily define methods for loading and comparing specific instances. This can give you cleaner code that reads far more naturally. You can also avoid defining dozens of constants or referencing magic values (i.e. no more hard-coded strings or ids in the code to look up specific records).
|
|
10
10
|
|
|
11
|
+
## Table of Contents
|
|
12
|
+
|
|
13
|
+
- [Usage](#usage)
|
|
14
|
+
- [Specifying Data Files](#specifying-data-files)
|
|
15
|
+
- [Named Instances](#named-instances)
|
|
16
|
+
- [Documenting Named Instance Helpers](#documenting-named-instance-helpers)
|
|
17
|
+
- [Caching](#caching)
|
|
18
|
+
- [Loading Data](#loading-data)
|
|
19
|
+
- [Testing](#testing)
|
|
20
|
+
- [Installation](#installation)
|
|
21
|
+
- [Contributing](#contributing)
|
|
22
|
+
- [License](#license)
|
|
23
|
+
|
|
11
24
|
## Usage
|
|
12
25
|
|
|
13
26
|
In the examples below, suppose we have a simple `Status` model in which each row has an id and a name, and the name can only have a handful of statuses: "Pending", "In Progress", and "Completed".
|
|
@@ -55,7 +68,9 @@ class Status < ApplicationRecord
|
|
|
55
68
|
|
|
56
69
|
You cannot update the value of the key attribute in a record in the data file. If you do, a new record will be created and the existing record will be left unchanged.
|
|
57
70
|
|
|
58
|
-
You can specify data files as relative paths. This can be done by setting the `SupportTableData.data_directory` value. You can override this value for a model by setting the `support_table_data_directory` attribute on its class.
|
|
71
|
+
You can specify data files as relative paths. This can be done by setting the `SupportTableData.data_directory` value. You can override this value for a model by setting the `support_table_data_directory` attribute on its class. Otherwise, relative file paths will be resolved from the current working directory. You must define the directory to load relative files from before loading your model classes.
|
|
72
|
+
|
|
73
|
+
In a Rails application, `SupportTableData.data_directory` will be automatically set to `db/support_tables/`. This can be overridden by setting the `config.support_table.data_directory` option in the Rails application configuration.
|
|
59
74
|
|
|
60
75
|
**Note**: If you're using CSV files and Ruby 3.4 or higher, you'll need to include the `csv` gem in your Gemfile since it was removed from the standard library in Ruby 3.4.
|
|
61
76
|
|
|
@@ -109,7 +124,6 @@ Helper methods will not override already defined methods on a model class. If a
|
|
|
109
124
|
|
|
110
125
|
You can also define helper methods for named instance attributes. These helper methods will return the hard coded values from the data file. Calling these methods does not require a database connection.
|
|
111
126
|
|
|
112
|
-
|
|
113
127
|
```ruby
|
|
114
128
|
class Status < ApplicationRecord
|
|
115
129
|
include SupportTableData
|
|
@@ -171,6 +185,21 @@ completed:
|
|
|
171
185
|
group_name: done
|
|
172
186
|
```
|
|
173
187
|
|
|
188
|
+
#### Documenting Named Instance Helpers
|
|
189
|
+
|
|
190
|
+
In a Rails application, you can add YARD documentation for the named instance helpers by running the rake task `support_table_data:yard_docs`. This will add YARD comments to your model classes for each of the named instance helper methods defined on the model. Adding this documentation will help IDEs provide better code completion and inline documentation for the helper methods and expose the methods to AI agents.
|
|
191
|
+
|
|
192
|
+
To update a single model file, pass an optional file path argument, for example: `bundle exec rake "support_table_data:yard_docs[app/models/status.rb]"`.
|
|
193
|
+
|
|
194
|
+
The default behavior is to add the documentation comments at the end of the model class by reopening the class definition. If you prefer to have the documentation comments appear elsewhere in the file, you can add the following markers to your model class and the YARD documentation will be inserted between these markers.
|
|
195
|
+
|
|
196
|
+
```ruby
|
|
197
|
+
# Begin YARD docs for support_table_data
|
|
198
|
+
# End YARD docs for support_table_data
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
A good practice is to add a check to your CI pipeline to ensure the documentation is always up to date. You can run the rake task `support_table_data:yard_docs:verify` to do this. It will exit with an error if any models do not have up to date documentation.
|
|
202
|
+
|
|
174
203
|
### Caching
|
|
175
204
|
|
|
176
205
|
You can use the companion [support_table_cache gem](https://github.com/bdurand/support_table_cache) to add caching support to your models. That way your application won't need to constantly query the database for records that will never change.
|
|
@@ -198,6 +227,9 @@ class Thing < ApplicationRecord
|
|
|
198
227
|
end
|
|
199
228
|
```
|
|
200
229
|
|
|
230
|
+
> [!TIP]
|
|
231
|
+
> The [support_table](https://github.com/bdurand/support_table) gem combines both gems in a drop in solution for Rails applications.
|
|
232
|
+
|
|
201
233
|
### Loading Data
|
|
202
234
|
|
|
203
235
|
Calling `sync_table_data!` on your model class will synchronize the data in the database table with the values from the data files.
|
|
@@ -246,18 +278,33 @@ end
|
|
|
246
278
|
|
|
247
279
|
If you use a method to set a `has_many` association on your model, you **must** set the `autosave` option to `true` on the association (see the above example). This will ensure the association records are always saved even if there were no changes to the parent record.
|
|
248
280
|
|
|
249
|
-
You need to call `SupportTableData.sync_all!` when deploying your application. This gem includes a rake task `support_table_data:sync` that is suitable for hooking into deploy
|
|
281
|
+
You will need to call `SupportTableData.sync_all!` when deploying your application or running your test suite. This gem includes a rake task `support_table_data:sync` that is suitable for hooking into deploy or CI scripts.
|
|
282
|
+
|
|
283
|
+
This task is automatically run whenever you run any of these Rails tasks so if these are already part of your deploy or CI scripts, then no additional setup is required:
|
|
284
|
+
|
|
285
|
+
- `db:seed`
|
|
286
|
+
- `db:seed:replant`
|
|
287
|
+
- `db:prepare`
|
|
288
|
+
- `db:test:prepare`
|
|
289
|
+
- `db:fixtures:load`
|
|
290
|
+
|
|
291
|
+
You can disable these task enhancements by setting `config.support_table.auto_sync = false` in your Rails application configuration.
|
|
292
|
+
|
|
293
|
+
> [!TIP]
|
|
294
|
+
> If you also want to hook into the `db:migrate` task so that syncs are run immediately after database migrations, you can do this by adding code to a Rakefile in your application's `lib/tasks` directory. Migrations do funny things with the database connection especially when using multiple databases so you need to re-establish the connection before syncing the support table data.
|
|
250
295
|
|
|
251
296
|
```ruby
|
|
252
297
|
if Rake::Task.task_defined?("db:migrate")
|
|
253
298
|
Rake::Task["db:migrate"].enhance do
|
|
299
|
+
# The main database connection may have artifacts from the migration, so re-establish it
|
|
300
|
+
# to get a clean connection before syncing support table data.
|
|
301
|
+
ActiveRecord::Base.establish_connection
|
|
302
|
+
|
|
254
303
|
Rake::Task["support_table_data:sync"].invoke
|
|
255
304
|
end
|
|
256
305
|
end
|
|
257
306
|
```
|
|
258
307
|
|
|
259
|
-
Enhancing the `db:migrate` task also ensures that local development environments will stay up to date.
|
|
260
|
-
|
|
261
308
|
### Testing
|
|
262
309
|
|
|
263
310
|
You must also call `SupportTableData.sync_all!` before running your test suite. This method should be called in the test suite setup code after any data in the test database has been purged and before any tests are run.
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.
|
|
1
|
+
1.5.1
|