familia 2.0.0.pre10 → 2.0.0.pre13

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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +2 -3
  3. data/CHANGELOG.rst +507 -0
  4. data/CLAUDE.md +5 -55
  5. data/Gemfile +1 -6
  6. data/Gemfile.lock +13 -7
  7. data/changelog.d/README.md +45 -34
  8. data/changelog.d/scriv.ini +5 -0
  9. data/docs/archive/FAMILIA_RELATIONSHIPS.md +1 -1
  10. data/docs/archive/FAMILIA_UPDATE.md +1 -1
  11. data/docs/archive/README.md +15 -19
  12. data/docs/guides/Feature-System-Autoloading.md +228 -0
  13. data/docs/guides/Home.md +1 -1
  14. data/docs/guides/Implementation-Guide.md +1 -1
  15. data/docs/guides/relationships-methods.md +1 -1
  16. data/docs/guides/time-utilities.md +221 -0
  17. data/docs/migrating/.gitignore +2 -0
  18. data/docs/migrating/v2.0.0-pre.md +84 -0
  19. data/docs/migrating/v2.0.0-pre11.md +253 -0
  20. data/docs/migrating/v2.0.0-pre12.md +306 -0
  21. data/docs/migrating/v2.0.0-pre13.md +329 -0
  22. data/docs/migrating/v2.0.0-pre5.md +110 -0
  23. data/docs/migrating/v2.0.0-pre6.md +154 -0
  24. data/docs/migrating/v2.0.0-pre7.md +222 -0
  25. data/docs/overview.md +6 -7
  26. data/{examples/redis_command_validation_example.rb → docs/reference/auditing_database_commands.rb} +29 -32
  27. data/examples/autoloader/mega_customer/safe_dump_fields.rb +6 -0
  28. data/examples/autoloader/mega_customer.rb +17 -0
  29. data/examples/{bit_encoding_integration.rb → permissions.rb} +30 -27
  30. data/examples/{relationships_basic.rb → relationships.rb} +2 -3
  31. data/examples/safe_dump.rb +281 -0
  32. data/familia.gemspec +5 -4
  33. data/lib/familia/autoloader.rb +53 -0
  34. data/lib/familia/base.rb +57 -0
  35. data/lib/familia/data_type.rb +4 -0
  36. data/lib/familia/encryption/encrypted_data.rb +4 -4
  37. data/lib/familia/encryption/manager.rb +6 -4
  38. data/lib/familia/{encryption_request_cache.rb → encryption/request_cache.rb} +1 -1
  39. data/lib/familia/encryption.rb +1 -1
  40. data/lib/familia/errors.rb +5 -0
  41. data/lib/familia/features/autoloadable.rb +113 -0
  42. data/lib/familia/features/encrypted_fields/concealed_string.rb +4 -2
  43. data/lib/familia/features/expiration.rb +4 -0
  44. data/lib/familia/features/external_identifier.rb +310 -0
  45. data/lib/familia/features/object_identifier.rb +307 -0
  46. data/lib/familia/features/quantization.rb +5 -0
  47. data/lib/familia/features/safe_dump.rb +74 -73
  48. data/lib/familia/features.rb +109 -17
  49. data/lib/familia/field_type.rb +2 -0
  50. data/lib/familia/horreum/core/serialization.rb +3 -3
  51. data/lib/familia/horreum/subclass/definition.rb +50 -7
  52. data/lib/familia/horreum.rb +2 -0
  53. data/lib/familia/json_serializer.rb +70 -0
  54. data/lib/familia/logging.rb +12 -10
  55. data/lib/familia/refinements/logger_trace.rb +57 -0
  56. data/lib/familia/refinements/snake_case.rb +40 -0
  57. data/lib/familia/refinements/time_utils.rb +248 -0
  58. data/lib/familia/refinements.rb +3 -49
  59. data/lib/familia/secure_identifier.rb +51 -75
  60. data/lib/familia/utils.rb +2 -0
  61. data/lib/familia/validation/{test_helpers.rb → validation_helpers.rb} +2 -2
  62. data/lib/familia/validation.rb +1 -1
  63. data/lib/familia/verifiable_identifier.rb +162 -0
  64. data/lib/familia/version.rb +1 -1
  65. data/lib/familia.rb +15 -2
  66. data/try/core/autoloader_try.rb +112 -0
  67. data/try/core/extensions_try.rb +38 -21
  68. data/try/core/familia_extended_try.rb +4 -3
  69. data/try/core/secure_identifier_try.rb +47 -18
  70. data/try/core/time_utils_try.rb +130 -0
  71. data/try/core/verifiable_identifier_try.rb +171 -0
  72. data/try/data_types/datatype_base_try.rb +3 -2
  73. data/try/features/autoloadable/autoloadable_try.rb +61 -0
  74. data/try/features/encrypted_fields/concealed_string_core_try.rb +8 -3
  75. data/try/features/encrypted_fields/secure_by_default_behavior_try.rb +59 -17
  76. data/try/features/encrypted_fields/universal_serialization_safety_try.rb +36 -12
  77. data/try/features/{external_identifiers/external_identifiers_try.rb → external_identifier/external_identifier_try.rb} +25 -28
  78. data/try/features/feature_improvements_try.rb +127 -0
  79. data/try/features/{object_identifiers/object_identifiers_integration_try.rb → object_identifier/object_identifier_integration_try.rb} +28 -30
  80. data/try/features/{object_identifiers/object_identifiers_try.rb → object_identifier/object_identifier_try.rb} +13 -13
  81. data/try/features/real_feature_integration_try.rb +8 -7
  82. data/try/features/safe_dump/safe_dump_autoloading_try.rb +111 -0
  83. data/try/features/safe_dump/safe_dump_try.rb +8 -9
  84. data/try/helpers/test_helpers.rb +41 -17
  85. data/try/integration/cross_component_try.rb +3 -1
  86. metadata +61 -26
  87. data/CHANGELOG.md +0 -184
  88. data/changelog.d/fragments/.keep +0 -0
  89. data/changelog.d/template.md.j2 +0 -29
  90. data/lib/familia/core_ext.rb +0 -135
  91. data/lib/familia/features/external_identifiers/external_identifier_field_type.rb +0 -120
  92. data/lib/familia/features/external_identifiers.rb +0 -111
  93. data/lib/familia/features/object_identifiers/object_identifier_field_type.rb +0 -91
  94. data/lib/familia/features/object_identifiers.rb +0 -194
  95. data/setup.cfg +0 -12
@@ -0,0 +1,221 @@
1
+ # Time Utilities Guide
2
+
3
+ Familia provides a comprehensive time utilities refinement that adds convenient time conversion and age calculation methods to Ruby's `Numeric` and `String` classes.
4
+
5
+ ## Overview
6
+
7
+ The `Familia::Refinements::TimeUtils` module extends Ruby's built-in classes with intuitive time manipulation methods:
8
+
9
+ ```ruby
10
+ using Familia::Refinements::TimeUtils
11
+
12
+ 2.hours #=> 7200 (seconds)
13
+ "30m".in_seconds #=> 1800
14
+ timestamp.days_old #=> 5.2
15
+ ```
16
+
17
+ ## Time Constants
18
+
19
+ Familia uses **Gregorian year** calculations for consistent time conversions:
20
+
21
+ ```ruby
22
+ PER_YEAR = 31_556_952.0 # 365.2425 days (accounts for leap years)
23
+ PER_MONTH = 2_629_746.0 # PER_YEAR / 12 (30.437 days)
24
+ PER_WEEK = 604_800.0 # 7 days
25
+ PER_DAY = 86_400.0 # 24 hours
26
+ ```
27
+
28
+ ### Why Gregorian Year?
29
+
30
+ The key design decision ensures **mathematical consistency**:
31
+
32
+ ```ruby
33
+ 12.months == 1.year #=> true (both equal 31,556,952 seconds)
34
+ ```
35
+
36
+ This prevents subtle bugs where `12.months` and `1.year` would differ by ~5.8 hours.
37
+
38
+ ## Basic Time Conversions
39
+
40
+ ### Converting Numbers to Time Units
41
+
42
+ ```ruby
43
+ using Familia::Refinements::TimeUtils
44
+
45
+ # Singular and plural forms work identically
46
+ 1.second #=> 1
47
+ 30.seconds #=> 30
48
+ 5.minutes #=> 300
49
+ 2.hours #=> 7200
50
+ 3.days #=> 259200
51
+ 1.week #=> 604800
52
+ 2.months #=> 5259492
53
+ 1.year #=> 31556952
54
+ ```
55
+
56
+ ### Converting Time Units Back
57
+
58
+ ```ruby
59
+ 7200.in_hours #=> 2.0
60
+ 259200.in_days #=> 3.0
61
+ 5259492.in_months #=> 2.0
62
+ 31556952.in_years #=> 1.0
63
+ ```
64
+
65
+ ## String Time Parsing
66
+
67
+ Parse human-readable time strings:
68
+
69
+ ```ruby
70
+ "30s".in_seconds #=> 30.0
71
+ "5m".in_seconds #=> 300.0
72
+ "2h".in_seconds #=> 7200.0
73
+ "1d".in_seconds #=> 86400.0
74
+ "1w".in_seconds #=> 604800.0
75
+ "2mo".in_seconds #=> 5259492.0
76
+ "1y".in_seconds #=> 31556952.0
77
+ ```
78
+
79
+ ### Supported String Formats
80
+
81
+ | Unit | Abbreviations | Example |
82
+ |------|---------------|---------|
83
+ | Microseconds | `us`, `μs`, `microsecond`, `microseconds` | `"500us"` |
84
+ | Milliseconds | `ms`, `millisecond`, `milliseconds` | `"250ms"` |
85
+ | Seconds | `s`, `second`, `seconds` | `"30s"` |
86
+ | Minutes | `m`, `minute`, `minutes` | `"15m"` |
87
+ | Hours | `h`, `hour`, `hours` | `"2h"` |
88
+ | Days | `d`, `day`, `days` | `"7d"` |
89
+ | Weeks | `w`, `week`, `weeks` | `"2w"` |
90
+ | Months | `mo`, `month`, `months` | `"6mo"` |
91
+ | Years | `y`, `year`, `years` | `"1y"` |
92
+
93
+ **Note**: Use `"mo"` for months to avoid confusion with `"m"` (minutes).
94
+
95
+ ## Age Calculations
96
+
97
+ Calculate how old timestamps are:
98
+
99
+ ```ruby
100
+ # Basic age calculation
101
+ old_timestamp = 2.days.ago.to_i
102
+ old_timestamp.age_in(:days) #=> ~2.0
103
+ old_timestamp.age_in(:hours) #=> ~48.0
104
+ old_timestamp.age_in(:months) #=> ~0.066
105
+
106
+ # Convenience methods
107
+ old_timestamp.days_old #=> ~2.0
108
+ old_timestamp.hours_old #=> ~48.0
109
+ old_timestamp.minutes_old #=> ~2880.0
110
+ old_timestamp.weeks_old #=> ~0.28
111
+ old_timestamp.months_old #=> ~0.066
112
+ old_timestamp.years_old #=> ~0.005
113
+
114
+ # Calculate age from specific reference time
115
+ past_timestamp = 1.week.ago.to_i
116
+ reference_time = 3.days.ago
117
+ past_timestamp.age_in(:days, reference_time) #=> ~4.0
118
+ ```
119
+
120
+ ## Time Comparisons
121
+
122
+ ```ruby
123
+ timestamp = 2.hours.ago.to_i
124
+
125
+ # Check if older than duration
126
+ timestamp.older_than?(1.hour) #=> true
127
+ timestamp.older_than?(3.hours) #=> false
128
+
129
+ # Check if newer than duration (future)
130
+ future_timestamp = 1.hour.from_now.to_i
131
+ future_timestamp.newer_than?(30.minutes) #=> true
132
+
133
+ # Check if within duration of now (past or future)
134
+ timestamp.within?(3.hours) #=> true
135
+ timestamp.within?(1.hour) #=> false
136
+ ```
137
+
138
+ ## Practical Examples
139
+
140
+ ### Cache Expiration
141
+
142
+ ```ruby
143
+ using Familia::Refinements::TimeUtils
144
+
145
+ class CacheEntry < Familia::Horreum
146
+ field :data
147
+ field :created_at
148
+
149
+ def expired?
150
+ created_at.to_i.older_than?(1.hour)
151
+ end
152
+
153
+ def cache_age
154
+ created_at.to_i.minutes_old
155
+ end
156
+ end
157
+ ```
158
+
159
+ ### Session Management
160
+
161
+ ```ruby
162
+ class UserSession < Familia::Horreum
163
+ field :last_active
164
+
165
+ def stale?
166
+ last_active.to_i.older_than?(30.minutes)
167
+ end
168
+
169
+ def session_duration
170
+ "Active for #{last_active.to_i.hours_old.round(1)} hours"
171
+ end
172
+ end
173
+ ```
174
+
175
+ ### Data Retention
176
+
177
+ ```ruby
178
+ def cleanup_old_logs
179
+ Log.all.select do |log|
180
+ log.timestamp.to_i.older_than?(30.days)
181
+ end.each(&:destroy)
182
+ end
183
+ ```
184
+
185
+ ## Important Notes
186
+
187
+ ### Calendar vs. Precise Time
188
+
189
+ Familia's time utilities use **average durations** suitable for:
190
+ - Age calculations
191
+ - Cache expiration
192
+ - Time-based cleanup
193
+ - General time arithmetic
194
+
195
+ For **calendar-aware operations** (exact months, leap years), use Ruby's `Date`/`Time` classes:
196
+
197
+ ```ruby
198
+ # For average durations (Familia)
199
+ user_age = signup_date.to_i.months_old #=> 6.2
200
+
201
+ # For exact calendar operations (Ruby stdlib)
202
+ exact_months = Date.today.months_since(signup_date) #=> 6
203
+ ```
204
+
205
+ ### Thread Safety
206
+
207
+ All time utility methods are thread-safe and work with frozen objects.
208
+
209
+ ## Migration from v1.x
210
+
211
+ If upgrading from earlier versions:
212
+
213
+ ```ruby
214
+ # Old behavior (inconsistent)
215
+ 12.months != 1.year # Different values
216
+
217
+ # New behavior (consistent)
218
+ 12.months == 1.year # Same value: 31,556,952 seconds
219
+ ```
220
+
221
+ Update any code that relied on the old 365-day year constant to expect the new Gregorian year values.
@@ -0,0 +1,2 @@
1
+ # Even all wiki markdown docs get the blues
2
+ !*.md
@@ -0,0 +1,84 @@
1
+ # Migrating Guide: v1.x to v2.0.0-pre
2
+
3
+ This guide covers migrating from Familia v1.x to the v2.0.0-pre foundation release.
4
+
5
+ ## Overview
6
+
7
+ The v2.0.0-pre series represents a major modernization of Familia with:
8
+ - Complete API redesign for clarity and consistency
9
+ - Valkey compatibility alongside Redis support
10
+ - Ruby 3.4+ modernization with improved thread safety
11
+ - New connection pooling architecture
12
+
13
+ ## Step-by-Step Migration
14
+
15
+ ### 1. Update Connection Configuration
16
+
17
+ **Before (v1.x):**
18
+ ```ruby
19
+ Familia.connect('redis://localhost:6379/0')
20
+ ```
21
+
22
+ **After (v2.0.0-pre):**
23
+ ```ruby
24
+ Familia.configure do |config|
25
+ config.redis_uri = 'redis://localhost:6379/0'
26
+ config.connection_pool = true
27
+ end
28
+ ```
29
+
30
+ ### 2. Migrate Identifier Declarations
31
+
32
+ **Before (v1.x):**
33
+ ```ruby
34
+ class User < Familia::Base
35
+ identifier :user_id
36
+ end
37
+ ```
38
+
39
+ **After (v2.0.0-pre):**
40
+ ```ruby
41
+ class User < Familia::Horreum
42
+ identifier_field :user_id
43
+ end
44
+ ```
45
+
46
+ ### 3. Update Feature Activations
47
+
48
+ **Before (v1.x):**
49
+ ```ruby
50
+ class User < Familia::Base
51
+ include Familia::Features::Expiration
52
+ end
53
+ ```
54
+
55
+ **After (v2.0.0-pre):**
56
+ ```ruby
57
+ class User < Familia::Horreum
58
+ feature :expiration
59
+ end
60
+ ```
61
+
62
+ ### 4. Review Method Calls
63
+
64
+ Several methods were renamed for consistency:
65
+
66
+ | v1.x Method | v2.0.0-pre Method | Notes |
67
+ |-------------|------------------|-------|
68
+ | `delete` | `destroy` | More semantic naming |
69
+ | `exists` | `exists?` | Ruby predicate convention |
70
+ | `dump` | `serialize` | Clearer intent |
71
+
72
+ ## Breaking Changes
73
+
74
+ - `Familia::Base` replaced by `Familia::Horreum`
75
+ - Connection configuration moved to block-based setup
76
+ - Feature inclusion changed from `include` to `feature` declarations
77
+ - Several method names updated for consistency
78
+
79
+ ## Next Steps
80
+
81
+ After completing the foundation migration:
82
+ 1. Review [Security Feature Adoption](v2.0.0-pre5.md) for encrypted fields
83
+ 2. See [Architecture Migration](v2.0.0-pre6.md) for persistence improvements
84
+ 3. Explore [Relationships Migration](v2.0.0-pre7.md) for the new relationship system
@@ -0,0 +1,253 @@
1
+ # Migrating Guide: v2.0.0-pre11
2
+
3
+ This version introduces significant improvements to Familia's feature system, making it easier to organize and use features across complex projects.
4
+
5
+ ## Enhanced Feature System
6
+
7
+ ### Model-Specific Feature Registration
8
+
9
+ Previously, all features were registered globally. Now you can register features specific to individual model classes, allowing for better organization and namespace management.
10
+
11
+ #### Before
12
+ ```ruby
13
+ # Global feature registration only
14
+ module MyProjectFeature
15
+ # Feature implementation
16
+ end
17
+ Familia::Base.add_feature MyProjectFeature, :my_project_feature
18
+
19
+ class Customer < Familia::Horreum
20
+ feature :my_project_feature
21
+ end
22
+
23
+ class Session < Familia::Horreum
24
+ feature :my_project_feature # Same global feature
25
+ end
26
+ ```
27
+
28
+ #### After
29
+ ```ruby
30
+ # Model-specific feature registration
31
+ module CustomerSpecificFeature
32
+ # Feature implementation
33
+ end
34
+
35
+ # Register feature only for Customer and its subclasses
36
+ Customer.add_feature CustomerSpecificFeature, :customer_specific
37
+
38
+ class Customer < Familia::Horreum
39
+ feature :customer_specific # Available via Customer's registry
40
+ end
41
+
42
+ class PremiumCustomer < Customer
43
+ feature :customer_specific # Inherited via ancestry chain
44
+ end
45
+
46
+ class Session < Familia::Horreum
47
+ # feature :customer_specific # Not available - would raise error
48
+ end
49
+ ```
50
+
51
+ **Benefits:**
52
+ - Features can have the same name across different model hierarchies
53
+ - Standardized naming: `deprecated_fields.rb` instead of `customer_deprecated_fields.rb`
54
+ - Natural inheritance through Ruby's class hierarchy
55
+
56
+ ## SafeDump DSL Improvements
57
+
58
+ The new DSL replaces the brittle `@safe_dump_fields` class instance variable pattern with clean, explicit methods.
59
+
60
+ ### Before
61
+ ```ruby
62
+ class Customer < Familia::Horreum
63
+ feature :safe_dump
64
+
65
+ # Brittle - hard to move to feature modules, confusing syntax
66
+ @safe_dump_fields = [
67
+ :custid,
68
+ :email,
69
+ { active: ->(obj) { obj.active? } },
70
+ { display_name: ->(obj) { "#{obj.name} (#{obj.custid})" } }
71
+ ]
72
+ end
73
+ ```
74
+
75
+ ### After
76
+ ```ruby
77
+ class Customer < Familia::Horreum
78
+ feature :safe_dump
79
+
80
+ # Clean DSL - easy to understand and organize
81
+ safe_dump_field :custid
82
+ safe_dump_field :email
83
+ safe_dump_field :active, ->(obj) { obj.active? }
84
+ safe_dump_field :display_name, ->(obj) { "#{obj.name} (#{obj.custid})" }
85
+
86
+ # Or define multiple fields at once
87
+ safe_dump_fields :created, :updated, { status: ->(obj) { obj.role } }
88
+ end
89
+ ```
90
+
91
+ **New methods available:**
92
+ - `safe_dump_field(name, callable = nil)` - Define a single field
93
+ - `safe_dump_fields(*fields)` - Define multiple fields or get field names
94
+ - `safe_dump_field_names` - Get array of field names
95
+ - `safe_dump_field_map` - Get the internal callable map
96
+
97
+ **Backward Compatibility:**
98
+ - `set_safe_dump_fields(*fields)` - Legacy setter method (still works)
99
+ - The old `@safe_dump_fields` pattern is no longer supported
100
+
101
+ ## Auto-loading Features
102
+
103
+ ### Before: Manual Loading
104
+ ```ruby
105
+ # customer/features.rb
106
+
107
+ # Manual feature loading (copied from Familia)
108
+ features_dir = File.join(__dir__, 'features')
109
+ if Dir.exist?(features_dir)
110
+ Dir.glob(File.join(features_dir, '*.rb')).each do |feature_file|
111
+ require_relative feature_file
112
+ end
113
+ end
114
+
115
+ class Customer < Familia::Horreum
116
+ # Features now available for use
117
+ feature :deprecated_fields
118
+ end
119
+ ```
120
+
121
+ ### After: Automatic Loading
122
+ ```ruby
123
+ # customer/features.rb
124
+
125
+ class Customer < Familia::Horreum
126
+ module Features
127
+ include Familia::Autoloader
128
+ # Automatically discovers and loads all *.rb files from customer/features/
129
+ end
130
+ end
131
+
132
+ class Customer < Familia::Horreum
133
+ # Features automatically loaded and available
134
+ feature :deprecated_fields
135
+ end
136
+ ```
137
+
138
+ **Directory structure this enables:**
139
+ ```
140
+ models/
141
+ ├── customer/
142
+ │ ├── features/
143
+ │ │ ├── deprecated_fields.rb # Standardized names!
144
+ │ │ ├── legacy_support.rb
145
+ │ │ └── stripe_integration.rb
146
+ │ └── features.rb # Include Autoloader here
147
+ ├── session/
148
+ │ ├── features/
149
+ │ │ ├── deprecated_fields.rb # Same name, different implementation
150
+ │ │ └── expiration_hooks.rb
151
+ │ └── features.rb
152
+ └── customer.rb
153
+ ```
154
+
155
+ ## Field Definitions in Feature Modules
156
+
157
+ Feature modules can now define fields directly in their `ClassMethods` modules. When a class extends the module, the field definitions execute in the extending class's context.
158
+
159
+ ### Example
160
+ ```ruby
161
+ # features/common_fields.rb
162
+
163
+ module CommonFields
164
+ def self.included(base)
165
+ base.extend ClassMethods
166
+ end
167
+
168
+ module ClassMethods
169
+ # These field calls execute in the extending class's context
170
+ field :created
171
+ field :updated
172
+ field :version
173
+
174
+ def touch_updated
175
+ self.updated = Time.now.to_i
176
+ end
177
+ end
178
+
179
+ Familia::Base.add_feature self, :common_fields
180
+ end
181
+
182
+ # Usage
183
+ class Customer < Familia::Horreum
184
+ feature :common_fields
185
+ # Now has :created, :updated, :version fields and touch_updated class method
186
+ end
187
+ ```
188
+
189
+ ## Migration Steps
190
+
191
+ ### 1. Update SafeDump Usage
192
+ Replace all `@safe_dump_fields` definitions with the new DSL:
193
+
194
+ ```ruby
195
+ # Find and replace pattern:
196
+ # Old: @safe_dump_fields = [:field1, :field2, { field3: ->(obj) { ... } }]
197
+ # New: safe_dump_fields :field1, :field2, { field3: ->(obj) { ... } }
198
+
199
+ # Or use individual field definitions for better readability:
200
+ safe_dump_field :field1
201
+ safe_dump_field :field2
202
+ safe_dump_field :field3, ->(obj) { ... }
203
+ ```
204
+
205
+ ### 2. Set Up Auto-loading (Optional)
206
+ If you have project-specific features, set up auto-loading:
207
+
208
+ ```ruby
209
+ # Create: models/[model_name]/features.rb
210
+ module YourProject
211
+ class ModelName < Familia::Horreum
212
+ module Features
213
+ include Familia::Autoloader
214
+ end
215
+ end
216
+ end
217
+
218
+ # Require this file before your model definitions
219
+ require_relative 'model_name/features'
220
+ ```
221
+
222
+ ### 3. Organize Features by Model (Optional)
223
+ Consider reorganizing shared feature names by model:
224
+
225
+ ```ruby
226
+ # Before: features/customer_deprecated_fields.rb
227
+ # After: models/customer/features/deprecated_fields.rb
228
+
229
+ # This allows multiple models to have their own deprecated_fields.rb
230
+ ```
231
+
232
+ ### 4. Test Your Changes
233
+ Run your test suite to ensure all SafeDump functionality works correctly:
234
+
235
+ ```ruby
236
+ # Verify SafeDump DSL works
237
+ model = YourModel.new(field1: 'value')
238
+ result = model.safe_dump
239
+ puts result.keys # Should include your defined fields
240
+ ```
241
+
242
+ ## Breaking Changes
243
+
244
+ 1. **`@safe_dump_fields` no longer supported** - Must migrate to DSL methods
245
+ 2. **SafeDump field order** - Fields are now returned in definition order via Hash keys (Ruby 1.9+ behavior)
246
+
247
+ ## New Capabilities Unlocked
248
+
249
+ 1. **Standardized feature names** across different models
250
+ 2. **Cleaner SafeDump definitions** that can be easily moved to feature modules
251
+ 3. **Automatic feature discovery** for better project organization
252
+ 4. **Model-specific feature registries** for better namespace management
253
+ 5. **Field definitions in feature modules** for shared functionality