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,110 @@
1
+ # Migrating Guide: Security Features (v2.0.0-pre5)
2
+
3
+ This guide covers adopting the security enhancements introduced in v2.0.0-pre5.
4
+
5
+ ## Security Feature Adoption
6
+
7
+ ### 1. Configure Encryption Keys
8
+
9
+ Before using encrypted fields, configure encryption keys:
10
+
11
+ ```ruby
12
+ Familia.configure do |config|
13
+ config.encryption_keys = {
14
+ v1: 'your-32-byte-base64-encoded-key==',
15
+ v2: 'newer-32-byte-base64-encoded-key=='
16
+ }
17
+ config.current_key_version = :v2
18
+ end
19
+ ```
20
+
21
+ **Key Management:**
22
+ - Use secure key storage (environment variables, key management services)
23
+ - Rotate keys regularly by adding new versions
24
+ - Never remove old key versions while data exists
25
+
26
+ ### 2. Identify Sensitive Fields
27
+
28
+ Mark fields that contain sensitive data:
29
+
30
+ **For Encryption:**
31
+ ```ruby
32
+ class Vault < Familia::Horreum
33
+ feature :encrypted_fields
34
+
35
+ field :name # Plaintext
36
+ encrypted_field :secret_key # Encrypted at rest
37
+ encrypted_field :api_token # Transparent access
38
+ end
39
+ ```
40
+
41
+ **For Transient Fields:**
42
+ ```ruby
43
+ class User < Familia::Horreum
44
+ feature :transient_fields
45
+
46
+ field :email # Persisted
47
+ transient_field :password # Never persisted
48
+ transient_field :session_token # Runtime only
49
+ end
50
+ ```
51
+
52
+ ### 3. Update Serialization Code
53
+
54
+ Handle `RedactedString` in serialization:
55
+
56
+ **Before:**
57
+ ```ruby
58
+ def to_json
59
+ { name: name, password: password }.to_json
60
+ end
61
+ ```
62
+
63
+ **After:**
64
+ ```ruby
65
+ def to_json
66
+ # RedactedString automatically excluded from serialization
67
+ { name: name }.to_json # password field omitted if transient
68
+ end
69
+ ```
70
+
71
+ **Manual RedactedString Handling:**
72
+ ```ruby
73
+ # Access original value when needed
74
+ password.reveal # Returns actual string value
75
+ password.redacted? # Returns true if redacted
76
+ ```
77
+
78
+ ### 4. Implement Key Rotation Procedures
79
+
80
+ **Rotation Process:**
81
+ 1. Add new key version to configuration
82
+ 2. Update `current_key_version`
83
+ 3. Re-encrypt existing data gradually
84
+ 4. Remove old keys after migration complete
85
+
86
+ **Example Rotation Script:**
87
+ ```ruby
88
+ # Add new key version
89
+ Familia.config.encryption_keys[:v3] = 'new-key'
90
+ Familia.config.current_key_version = :v3
91
+
92
+ # Re-encrypt existing records
93
+ Vault.all.each do |vault|
94
+ vault.save # Automatically uses new key version
95
+ end
96
+ ```
97
+
98
+ ## Security Best Practices
99
+
100
+ - **Environment Variables:** Store keys in environment variables, not code
101
+ - **Key Rotation:** Rotate encryption keys regularly (quarterly/annually)
102
+ - **Field Selection:** Only encrypt fields that truly need protection
103
+ - **Memory Clearing:** Use transient fields for temporary sensitive data
104
+ - **Logging:** Verify RedactedString prevents accidental logging
105
+
106
+ ## Next Steps
107
+
108
+ After implementing security features:
109
+ 1. Review [Architecture Migration](v2.0.0-pre6.md) for persistence improvements
110
+ 2. Explore [Relationships Migration](v2.0.0-pre7.md) for the relationship system
@@ -0,0 +1,154 @@
1
+ # Migrating Guide: Architecture Improvements (v2.0.0-pre6)
2
+
3
+ This guide covers the architecture enhancements and new persistence methods in v2.0.0-pre6.
4
+
5
+ ## Architecture Improvements
6
+
7
+ ### 1. Enhanced Persistence Operations
8
+
9
+ **New `save_if_not_exists` Method:**
10
+ ```ruby
11
+ user = User.new(email: 'user@example.com')
12
+
13
+ # Only save if the user doesn't already exist
14
+ if user.save_if_not_exists
15
+ puts "User created successfully"
16
+ else
17
+ puts "User already exists"
18
+ end
19
+ ```
20
+
21
+ **Atomic Persistence with Transactions:**
22
+ ```ruby
23
+ user.transaction do |conn|
24
+ conn.set(user.key, user.serialize)
25
+ conn.sadd("all_users", user.identifier)
26
+ conn.expire(user.key, user.ttl) if user.ttl
27
+ end
28
+ ```
29
+
30
+ ### 2. Modular Class Structure
31
+
32
+ The Horreum class structure was reorganized for better maintainability:
33
+
34
+ **Core Modules:**
35
+ - `Familia::Horreum::Core` - Essential functionality
36
+ - `Familia::Horreum::ClassMethods` - Class-level methods
37
+ - `Familia::Horreum::Serialization` - Object serialization
38
+ - `Familia::Horreum::Commands` - Redis command wrappers
39
+
40
+ **Feature System Improvements:**
41
+ - Dependency management between features
42
+ - Cleaner feature activation
43
+ - Better error handling for missing dependencies
44
+
45
+ ### 3. Enhanced Error Handling
46
+
47
+ **New Exception Types:**
48
+ ```ruby
49
+ begin
50
+ user.save!
51
+ rescue Familia::PersistenceError => e
52
+ puts "Failed to save: #{e.message}"
53
+ rescue Familia::ValidationError => e
54
+ puts "Validation failed: #{e.message}"
55
+ end
56
+ ```
57
+
58
+ **Improved Data Consistency:**
59
+ - Automatic retry for transient Redis connection issues
60
+ - Better handling of concurrent modifications
61
+ - Enhanced validation before persistence operations
62
+
63
+ ## Migration Steps
64
+
65
+ ### 1. Update Error Handling
66
+
67
+ **Before (v2.0.0-pre5):**
68
+ ```ruby
69
+ begin
70
+ user.save
71
+ rescue => e
72
+ puts "Something went wrong: #{e}"
73
+ end
74
+ ```
75
+
76
+ **After (v2.0.0-pre6):**
77
+ ```ruby
78
+ begin
79
+ user.save
80
+ rescue Familia::PersistenceError => e
81
+ puts "Persistence failed: #{e.message}"
82
+ # Handle specific persistence issues
83
+ rescue Familia::ValidationError => e
84
+ puts "Invalid data: #{e.message}"
85
+ # Handle validation failures
86
+ end
87
+ ```
88
+
89
+ ### 2. Adopt Conditional Persistence
90
+
91
+ Replace existence checks with atomic operations:
92
+
93
+ **Before:**
94
+ ```ruby
95
+ user = User.new(email: email)
96
+ unless User.exists?(email)
97
+ user.save
98
+ end
99
+ ```
100
+
101
+ **After:**
102
+ ```ruby
103
+ user = User.new(email: email)
104
+ user.save_if_not_exists
105
+ ```
106
+
107
+ ### 3. Leverage Transaction Support
108
+
109
+ For complex operations, use transactions:
110
+
111
+ ```ruby
112
+ # Before - Multiple separate operations
113
+ user.save
114
+ user.tags.add(tag)
115
+ user.scores.add(score, timestamp)
116
+
117
+ # After - Atomic transaction
118
+ user.transaction do |conn|
119
+ conn.set(user.key, user.serialize)
120
+ conn.sadd(user.tags.key, tag)
121
+ conn.zadd(user.scores.key, timestamp, score)
122
+ end
123
+ ```
124
+
125
+ ## Performance Improvements
126
+
127
+ ### Connection Management
128
+ - Improved connection pooling with better resource utilization
129
+ - Reduced connection overhead through intelligent connection reuse
130
+ - Enhanced concurrent operation support
131
+
132
+ ### Feature System
133
+ - Lazy feature loading reduces memory footprint
134
+ - Optimized method dispatch for feature methods
135
+ - Better dependency resolution
136
+
137
+ ## Breaking Changes
138
+
139
+ ### Method Signatures
140
+ - Some internal methods changed signatures for better consistency
141
+ - Error handling improved with specific exception types
142
+ - Transaction block interface standardized
143
+
144
+ ### Feature Dependencies
145
+ - Features now explicitly declare dependencies
146
+ - Better error messages for missing feature requirements
147
+ - Automatic dependency resolution where possible
148
+
149
+ ## Next Steps
150
+
151
+ After completing architecture migration:
152
+ 1. Explore [Relationships Migration](v2.0.0-pre7.md) for the comprehensive relationship system
153
+ 2. Review updated documentation for architectural patterns
154
+ 3. Consider adopting new persistence patterns in your application
@@ -0,0 +1,222 @@
1
+ # Migrating Guide: Relationships System (v2.0.0-pre7)
2
+
3
+ This guide covers adopting the comprehensive relationships system introduced in v2.0.0-pre7.
4
+
5
+ ## Relationships System Overview
6
+
7
+ The v2.0.0-pre7 release introduces three powerful relationship types:
8
+
9
+ - **`tracked_in`** - Multi-presence tracking with score encoding
10
+ - **`indexed_by`** - O(1) hash-based lookups
11
+ - **`member_of`** - Bidirectional membership with collision-free naming
12
+
13
+ ## Migration Steps
14
+
15
+ ### 1. Enable Relationships Feature
16
+
17
+ Add the relationships feature to your models:
18
+
19
+ ```ruby
20
+ class Customer < Familia::Horreum
21
+ feature :relationships # Required for all relationship types
22
+
23
+ identifier_field :custid
24
+ field :custid, :name, :email
25
+ end
26
+ ```
27
+
28
+ ### 2. Choose Appropriate Relationship Types
29
+
30
+ **For Tracking Collections (sorted sets):**
31
+ ```ruby
32
+ class Customer < Familia::Horreum
33
+ feature :relationships
34
+
35
+ # Global tracking with score-based sorting
36
+ tracked_in :all_customers, type: :sorted_set, score: :created_at
37
+
38
+ # Scoped tracking
39
+ tracked_in :active_users, type: :sorted_set, score: :last_seen
40
+ end
41
+ ```
42
+
43
+ **For Fast Lookups (hash indexes):**
44
+ ```ruby
45
+ class Customer < Familia::Horreum
46
+ feature :relationships
47
+
48
+ # Global email index for O(1) lookups
49
+ indexed_by :email, :email_lookup, context: :global
50
+
51
+ # Domain-specific indexes
52
+ indexed_by :account_id, :account_lookup, context: Domain
53
+ end
54
+ ```
55
+
56
+ **For Bidirectional Membership:**
57
+ ```ruby
58
+ class Domain < Familia::Horreum
59
+ feature :relationships
60
+
61
+ # Belongs to customer's domains collection
62
+ member_of Customer, :domains, type: :set
63
+ end
64
+ ```
65
+
66
+ ### 3. Implement Permission Systems
67
+
68
+ For access-controlled relationships:
69
+
70
+ ```ruby
71
+ class Document < Familia::Horreum
72
+ feature :relationships
73
+ include Familia::Features::Relationships::PermissionManagement
74
+
75
+ # Permission-aware tracking
76
+ tracked_in Customer, :documents, score: :created_at
77
+
78
+ permission_tracking :user_permissions
79
+
80
+ def permission_bits
81
+ # Define permission levels (bit-encoded)
82
+ @permission_bits || 1 # Default: read-only
83
+ end
84
+ end
85
+ ```
86
+
87
+ ### 4. Update Queries
88
+
89
+ **Before (manual Redis operations):**
90
+ ```ruby
91
+ # Manual sorted set operations
92
+ redis.zadd("all_customers", customer.created_at, customer.custid)
93
+ customers = redis.zrange("all_customers", 0, -1)
94
+ ```
95
+
96
+ **After (relationship methods):**
97
+ ```ruby
98
+ # Automatic method generation
99
+ Customer.add_to_all_customers(customer)
100
+ customers = Customer.all_customers.to_a
101
+ ```
102
+
103
+ ## Relationship Method Patterns
104
+
105
+ ### `tracked_in` Methods
106
+ ```ruby
107
+ # Class methods generated:
108
+ Customer.add_to_all_customers(customer)
109
+ Customer.remove_from_all_customers(customer)
110
+ Customer.all_customers # Access sorted set directly
111
+ ```
112
+
113
+ ### `indexed_by` Methods
114
+ ```ruby
115
+ # Class methods generated:
116
+ Customer.add_to_email_lookup(customer)
117
+ Customer.remove_from_email_lookup(customer)
118
+ Customer.email_lookup.get(email) # O(1) lookup
119
+ ```
120
+
121
+ ### `member_of` Methods
122
+ ```ruby
123
+ # Instance methods generated:
124
+ domain.add_to_customer_domains(customer)
125
+ domain.remove_from_customer_domains(customer)
126
+ domain.in_customer_domains?(customer)
127
+ ```
128
+
129
+ ## Permission System Migration
130
+
131
+ ### Basic Permission Encoding
132
+ ```ruby
133
+ # Permission levels (bit-encoded)
134
+ READ = 1 # 001
135
+ WRITE = 4 # 100
136
+ DELETE = 32 # 100000
137
+ ADMIN = 128 # 10000000
138
+
139
+ # Combine permissions
140
+ user_permissions = READ | WRITE # Can read and write
141
+ admin_permissions = ADMIN # All permissions via hierarchy
142
+ ```
143
+
144
+ ### Time-Based Permission Scores
145
+ ```ruby
146
+ # Encode timestamp with permission bits
147
+ timestamp = Time.now.to_i
148
+ permissions = READ | WRITE
149
+ score = Familia::Features::Relationships::ScoreEncoding.encode_score(timestamp, permissions)
150
+
151
+ # Query by permission level
152
+ documents_with_write_access = customer.documents.accessible_items(
153
+ permissions: WRITE,
154
+ collection_key: customer.documents.key
155
+ )
156
+ ```
157
+
158
+ ## Performance Considerations
159
+
160
+ ### Relationship Type Selection
161
+
162
+ **Use `indexed_by` for:**
163
+ - Unique field lookups (email, username, ID)
164
+ - Fields that need O(1) access
165
+ - Reference relationships
166
+
167
+ **Use `tracked_in` for:**
168
+ - Time-ordered collections
169
+ - Scored/ranked relationships
170
+ - Permission-based access control
171
+
172
+ **Use `member_of` for:**
173
+ - Simple membership tracking
174
+ - Bidirectional relationships
175
+ - Set-based collections
176
+
177
+ ### Optimization Tips
178
+
179
+ **Batch Operations:**
180
+ ```ruby
181
+ # Instead of multiple individual operations
182
+ customers.each { |c| Customer.add_to_all_customers(c) }
183
+
184
+ # Use batch operations where available
185
+ Customer.all_customers.add_batch(customers.map(&:identifier),
186
+ customers.map(&:created_at))
187
+ ```
188
+
189
+ **Permission Queries:**
190
+ ```ruby
191
+ # Efficient permission filtering
192
+ accessible_docs = document.accessible_items(
193
+ collection_key: customer.documents.key,
194
+ minimum_permissions: READ
195
+ )
196
+ ```
197
+
198
+ ## Breaking Changes
199
+
200
+ ### Method Name Changes
201
+ - Relationship methods follow new naming patterns
202
+ - Previous manual Redis operations need updating
203
+ - Collection access methods standardized
204
+
205
+ ### Permission System
206
+ - New bit-encoded permission system
207
+ - Time-based scoring for temporal access
208
+ - Permission hierarchy implementation required
209
+
210
+ ## Next Steps
211
+
212
+ 1. **Analyze Existing Relationships:** Review current Redis operations for optimization opportunities
213
+ 2. **Choose Relationship Types:** Select appropriate types based on usage patterns
214
+ 3. **Implement Permissions:** Add access control where needed
215
+ 4. **Update Queries:** Replace manual operations with generated relationship methods
216
+ 5. **Test Performance:** Benchmark relationship operations under load
217
+
218
+ ## Resources
219
+
220
+ - [Relationships Methods Guide](../guides/relationships-methods.md) - Complete method reference
221
+ - [Relationships Guide](../guides/Relationships-Guide.md) - Implementation examples
222
+ - [Performance Guide](../guides/Implementation-Guide.md) - Optimization strategies
data/docs/overview.md CHANGED
@@ -118,17 +118,16 @@ This is ideal for temporary data like authentication tokens or cache entries.
118
118
 
119
119
  ### Safe Dumping for APIs
120
120
 
121
- Control which fields are exposed when serializing objects:
121
+ Control which fields are exposed when serializing objects using the clean DSL:
122
122
 
123
123
  ```ruby
124
124
  class User < Familia::Horreum
125
125
  feature :safe_dump
126
126
 
127
- @safe_dump_fields = [
128
- :id,
129
- :email,
130
- {full_name: ->(user) { "#{user.first_name} #{user.last_name}" }}
131
- ]
127
+ # Use clean DSL methods instead of @safe_dump_fields
128
+ safe_dump_field :id
129
+ safe_dump_field :email
130
+ safe_dump_field :full_name, ->(user) { "#{user.first_name} #{user.last_name}" }
132
131
 
133
132
  field :id, :email, :first_name, :last_name, :password_hash
134
133
  end
@@ -137,7 +136,7 @@ user.safe_dump
137
136
  #=> {id: "123", email: "alice@example.com", full_name: "Alice Smith"}
138
137
  ```
139
138
 
140
- Prevents accidental exposure of sensitive data in API responses.
139
+ The new DSL prevents accidental exposure of sensitive data and makes field definitions easier to organize in feature modules.
141
140
 
142
141
  ### Time-based Quantization
143
142
 
@@ -50,21 +50,21 @@ class TransferService
50
50
  end
51
51
  end
52
52
 
53
- puts "🧪 Redis Command Validation Framework Demo"
54
- puts "=" * 50
53
+ puts '🧪 Redis Command Validation Framework Demo'
54
+ puts '=' * 50
55
55
 
56
56
  # Clean up any existing test data
57
- cleanup_keys = Familia.dbclient.keys("account:*")
57
+ cleanup_keys = Familia.dbclient.keys('account:*')
58
58
  Familia.dbclient.del(*cleanup_keys) if cleanup_keys.any?
59
59
 
60
60
  # Example 1: Basic Command Recording
61
61
  puts "\n1. Basic Command Recording"
62
- puts "-" * 30
62
+ puts '-' * 30
63
63
 
64
64
  CommandRecorder = Familia::Validation::CommandRecorder
65
65
  CommandRecorder.start_recording
66
66
 
67
- account = Account.new(account_id: "acc001", balance: "1000", status: "active")
67
+ account = Account.new(account_id: 'acc001', balance: '1000', status: 'active')
68
68
  account.save
69
69
 
70
70
  commands = CommandRecorder.stop_recording
@@ -73,12 +73,12 @@ commands.commands.each { |cmd| puts " #{cmd}" }
73
73
 
74
74
  # Example 2: Transaction Detection
75
75
  puts "\n2. Transaction Detection"
76
- puts "-" * 30
76
+ puts '-' * 30
77
77
 
78
78
  CommandRecorder.start_recording
79
79
 
80
- acc1 = Account.new(account_id: "acc002", balance: "2000")
81
- acc2 = Account.new(account_id: "acc003", balance: "500")
80
+ acc1 = Account.new(account_id: 'acc002', balance: '2000')
81
+ acc2 = Account.new(account_id: 'acc003', balance: '500')
82
82
  acc1.save
83
83
  acc2.save
84
84
 
@@ -96,7 +96,7 @@ end
96
96
 
97
97
  # Example 3: Validation with Expectations DSL
98
98
  puts "\n3. Command Validation with Expectations"
99
- puts "-" * 30
99
+ puts '-' * 30
100
100
 
101
101
  begin
102
102
  validator = Familia::Validation::Validator.new
@@ -104,15 +104,15 @@ begin
104
104
  # This should pass - we expect the exact Redis commands
105
105
  result = validator.validate do |expect|
106
106
  expect.transaction do |tx|
107
- tx.hset("account:acc004:object", "balance", "1500")
108
- .hset("account:acc005:object", "balance", "1000")
109
- .hset("account:acc004:object", "last_updated", Familia::Validation::ArgumentMatcher.new(:any_string))
110
- .hset("account:acc005:object", "last_updated", Familia::Validation::ArgumentMatcher.new(:any_string))
107
+ tx.hset('account:acc004:object', 'balance', '1500')
108
+ .hset('account:acc005:object', 'balance', '1000')
109
+ .hset('account:acc004:object', 'last_updated', Familia::Validation::ArgumentMatcher.new(:any_string))
110
+ .hset('account:acc005:object', 'last_updated', Familia::Validation::ArgumentMatcher.new(:any_string))
111
111
  end
112
112
 
113
113
  # Execute the operation
114
- acc4 = Account.new(account_id: "acc004", balance: "2000")
115
- acc5 = Account.new(account_id: "acc005", balance: "500")
114
+ acc4 = Account.new(account_id: 'acc004', balance: '2000')
115
+ acc5 = Account.new(account_id: 'acc005', balance: '500')
116
116
  acc4.save
117
117
  acc5.save
118
118
 
@@ -121,51 +121,49 @@ begin
121
121
 
122
122
  puts "Validation result: #{result.valid? ? 'PASS ✅' : 'FAIL ❌'}"
123
123
  puts "Summary: #{result.summary}"
124
-
125
- rescue => e
124
+ rescue StandardError => e
126
125
  puts "Validation demo encountered error: #{e.message}"
127
- puts "This is expected as the framework needs Redis middleware integration"
126
+ puts 'This is expected as the framework needs Redis middleware integration'
128
127
  end
129
128
 
130
129
  # Example 4: Performance Analysis
131
130
  puts "\n4. Performance Analysis"
132
- puts "-" * 30
131
+ puts '-' * 30
133
132
 
134
133
  begin
135
134
  commands = Familia::Validation.capture_commands do
136
135
  # Create multiple accounts
137
136
  accounts = []
138
137
  (1..5).each do |i|
139
- account = Account.new(account_id: "perf#{i}", balance: "1000")
138
+ account = Account.new(account_id: "perf#{i}", balance: '1000')
140
139
  account.save
141
140
  accounts << account
142
141
  end
143
142
 
144
143
  # Perform operations
145
- accounts[0].balance = "1100"
144
+ accounts[0].balance = '1100'
146
145
  accounts[0].save
147
146
  end
148
147
 
149
148
  analyzer = Familia::Validation::PerformanceAnalyzer.new(commands)
150
149
  analysis = analyzer.analyze
151
150
 
152
- puts "Performance Analysis:"
151
+ puts 'Performance Analysis:'
153
152
  puts " Total Commands: #{analysis[:total_commands]}"
154
153
  puts " Command Types: #{analysis[:command_type_breakdown].keys.join(', ')}"
155
154
  puts " Efficiency Score: #{analysis[:efficiency_score]}/100"
156
-
157
- rescue => e
155
+ rescue StandardError => e
158
156
  puts "Performance analysis encountered error: #{e.message}"
159
157
  end
160
158
 
161
159
  # Example 5: Atomicity Validation
162
160
  puts "\n5. Atomicity Validation"
163
- puts "-" * 30
161
+ puts '-' * 30
164
162
 
165
163
  begin
166
164
  # Test atomic vs non-atomic operations
167
- acc6 = Account.new(account_id: "acc006", balance: "3000")
168
- acc7 = Account.new(account_id: "acc007", balance: "1000")
165
+ acc6 = Account.new(account_id: 'acc006', balance: '3000')
166
+ acc7 = Account.new(account_id: 'acc007', balance: '1000')
169
167
  acc6.save
170
168
  acc7.save
171
169
 
@@ -180,13 +178,12 @@ begin
180
178
  result = atomicity_validator.validate
181
179
 
182
180
  puts "Atomicity validation: #{result.valid? ? 'PASS ✅' : 'FAIL ❌'}"
183
-
184
- rescue => e
181
+ rescue StandardError => e
185
182
  puts "Atomicity validation encountered error: #{e.message}"
186
183
  end
187
184
 
188
185
  puts "\n6. Framework Architecture Overview"
189
- puts "-" * 30
186
+ puts '-' * 30
190
187
  puts "
191
188
  The Redis Command Validation Framework provides:
192
189
 
@@ -224,8 +221,8 @@ Key Benefits:
224
221
  "
225
222
 
226
223
  # Cleanup
227
- cleanup_keys = Familia.dbclient.keys("account:*")
224
+ cleanup_keys = Familia.dbclient.keys('account:*')
228
225
  Familia.dbclient.del(*cleanup_keys) if cleanup_keys.any?
229
226
 
230
227
  puts "\n🎉 Demo complete! The validation framework is ready for use."
231
- puts " See try/validation/ for comprehensive test examples."
228
+ puts ' See try/validation/ for comprehensive test examples.'
@@ -0,0 +1,6 @@
1
+ # examples/autoloader/mega_customer/safe_dump_fields.rb
2
+
3
+ # Extend the MegaCustomer class to add safe dump fields
4
+ class MegaCustomer
5
+ safe_dump_fields :custid, :username, :created_at, :updated_at
6
+ end
@@ -0,0 +1,17 @@
1
+ # examples/autoloader/mega_customer.rb
2
+
3
+ require_relative '../../lib/familia'
4
+
5
+ class MegaCustomer < Familia::Horreum
6
+ field :custid
7
+ field :username
8
+ field :email
9
+ field :fname
10
+ field :lname
11
+ field :display_name
12
+ field :created_at
13
+ field :updated_at
14
+
15
+ feature :safe_dump
16
+ # feature :deprecated_fields
17
+ end