column_anonymizer 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -1
- data/LICENSE +21 -0
- data/README.md +56 -57
- data/data.tar.gz +0 -0
- data/lib/column_anonymizer/anonymizer.rb +3 -3
- data/lib/column_anonymizer/schema_loader.rb +2 -2
- data/lib/column_anonymizer/version.rb +1 -1
- data/lib/generators/column_anonymizer/initializer/templates/column_anonymizer.rb +12 -2
- data/lib/generators/column_anonymizer/install/README +1 -1
- data/lib/generators/column_anonymizer/install/install_generator.rb +2 -2
- data/lib/generators/column_anonymizer/scan/scan_generator.rb +3 -3
- data/lib/tasks/column_anonymizer.rake +18 -22
- metadata +6 -17
- data/CUSTOM_GENERATORS_COMPLETE.md +0 -507
- data/CUSTOM_GENERATORS_GUIDE.md +0 -515
- data/CUSTOM_GENERATORS_IMPLEMENTATION.md +0 -471
- data/CUSTOM_GENERATORS_QUICK_REF.md +0 -95
- data/FEATURE_COMPLETE.md +0 -287
- data/GEMSPEC_FIX.md +0 -90
- data/IMPLEMENTATION_SUMMARY.md +0 -205
- data/QUICK_REFERENCE.md +0 -92
- data/RAKE_TASKS_GUIDE.md +0 -469
- data/RAKE_TASKS_IMPLEMENTATION.md +0 -363
- data/RAKE_TASKS_QUICK_REF.md +0 -164
- data/SCAN_GENERATOR_TEST.md +0 -141
- data/WORKFLOW_GUIDE.md +0 -368
- data/YAML_MIGRATION_GUIDE.md +0 -284
- /data/lib/generators/column_anonymizer/install/templates/{encrypted_columns.yml → anonymized_columns.yml} +0 -0
|
@@ -1,507 +0,0 @@
|
|
|
1
|
-
# ✅ Custom Generators Implementation Complete
|
|
2
|
-
|
|
3
|
-
## 🎯 Your Request
|
|
4
|
-
**"I want a way to add custom anonymization types from within the rails app. I am thinking it would be some ruby class somewhere that would define a custom type then it would get appended when we anonymize the data"**
|
|
5
|
-
|
|
6
|
-
## ✅ Delivered!
|
|
7
|
-
|
|
8
|
-
You can now register custom anonymization types from within your Rails app using a simple, flexible API.
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## 📦 What Was Created
|
|
13
|
-
|
|
14
|
-
### 1. **Enhanced Anonymizer Class**
|
|
15
|
-
**File**: `lib/column_anonymizer/anonymizer.rb`
|
|
16
|
-
|
|
17
|
-
**New Features:**
|
|
18
|
-
- `register(type, &block)` - Register custom generators
|
|
19
|
-
- `unregister(type)` - Remove custom generators
|
|
20
|
-
- `all_generators` - Get built-in + custom generators merged
|
|
21
|
-
- `generator_exists?(type)` - Check if a generator exists
|
|
22
|
-
- `reset_custom_generators!` - Clear custom generators (for testing)
|
|
23
|
-
- `BUILT_IN_GENERATORS` constant (renamed from `GENERATORS`)
|
|
24
|
-
- `@custom_generators` class instance variable to store custom types
|
|
25
|
-
|
|
26
|
-
### 2. **Initializer Generator**
|
|
27
|
-
**File**: `lib/generators/column_anonymizer/initializer/initializer_generator.rb`
|
|
28
|
-
|
|
29
|
-
Command: `rails generate column_anonymizer:initializer`
|
|
30
|
-
|
|
31
|
-
Creates: `config/initializers/column_anonymizer.rb` with:
|
|
32
|
-
- Example custom generators
|
|
33
|
-
- Helpful comments
|
|
34
|
-
- Common patterns
|
|
35
|
-
- List of built-in types
|
|
36
|
-
|
|
37
|
-
### 3. **Initializer Template**
|
|
38
|
-
**File**: `lib/generators/column_anonymizer/initializer/templates/column_anonymizer.rb`
|
|
39
|
-
|
|
40
|
-
Includes examples for:
|
|
41
|
-
- Simple masking (credit cards)
|
|
42
|
-
- Using Faker
|
|
43
|
-
- Custom business logic
|
|
44
|
-
- Format-specific patterns
|
|
45
|
-
- Using Rails models
|
|
46
|
-
- Date/time generators
|
|
47
|
-
- Complex multi-field logic
|
|
48
|
-
|
|
49
|
-
### 4. **Comprehensive Documentation**
|
|
50
|
-
- `CUSTOM_GENERATORS_GUIDE.md` (500+ lines) - Complete guide
|
|
51
|
-
- `CUSTOM_GENERATORS_QUICK_REF.md` - Quick reference
|
|
52
|
-
- Updated `README.md` - Custom generators section
|
|
53
|
-
- Updated `CHANGELOG.md` - Feature documentation
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## 🚀 How It Works
|
|
58
|
-
|
|
59
|
-
### Step 1: Generate Initializer
|
|
60
|
-
```bash
|
|
61
|
-
rails generate column_anonymizer:initializer
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
### Step 2: Register Custom Types
|
|
65
|
-
```ruby
|
|
66
|
-
# config/initializers/column_anonymizer.rb
|
|
67
|
-
|
|
68
|
-
ColumnAnonymizer::Anonymizer.register(:credit_card) do
|
|
69
|
-
"XXXX-XXXX-XXXX-#{rand(1000..9999)}"
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
ColumnAnonymizer::Anonymizer.register(:employee_id) do
|
|
73
|
-
"EMP-#{Time.now.year}-#{rand(10000..99999)}"
|
|
74
|
-
end
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### Step 3: Use in YAML Config
|
|
78
|
-
```yaml
|
|
79
|
-
# config/encrypted_columns.yml
|
|
80
|
-
User:
|
|
81
|
-
credit_card_number: credit_card # ← Custom type!
|
|
82
|
-
employee_number: employee_id # ← Custom type!
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### Step 4: Anonymize
|
|
86
|
-
```ruby
|
|
87
|
-
user = User.first
|
|
88
|
-
ColumnAnonymizer::Anonymizer.anonymize_model!(user)
|
|
89
|
-
|
|
90
|
-
# credit_card_number => "XXXX-XXXX-XXXX-4823"
|
|
91
|
-
# employee_number => "EMP-2026-47293"
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
|
|
96
|
-
## 🎨 Registration Patterns
|
|
97
|
-
|
|
98
|
-
### Block Syntax (Recommended)
|
|
99
|
-
```ruby
|
|
100
|
-
ColumnAnonymizer::Anonymizer.register(:custom_type) do
|
|
101
|
-
"VALUE-#{SecureRandom.hex(4)}"
|
|
102
|
-
end
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
### Lambda Syntax
|
|
106
|
-
```ruby
|
|
107
|
-
ColumnAnonymizer::Anonymizer.register(:uuid, -> { SecureRandom.uuid })
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### Callable Object
|
|
111
|
-
```ruby
|
|
112
|
-
class EmployeeIdGenerator
|
|
113
|
-
def self.call
|
|
114
|
-
"EMP-#{Time.now.year}-#{rand(10000..99999)}"
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
ColumnAnonymizer::Anonymizer.register(:employee_id, EmployeeIdGenerator)
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
---
|
|
122
|
-
|
|
123
|
-
## 📋 Example Custom Generators
|
|
124
|
-
|
|
125
|
-
### Credit Card Masking
|
|
126
|
-
```ruby
|
|
127
|
-
ColumnAnonymizer::Anonymizer.register(:credit_card) do
|
|
128
|
-
"XXXX-XXXX-XXXX-#{rand(1000..9999)}"
|
|
129
|
-
end
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
### License Plate
|
|
133
|
-
```ruby
|
|
134
|
-
ColumnAnonymizer::Anonymizer.register(:license_plate) do
|
|
135
|
-
letters = ('A'..'Z').to_a.sample(3).join
|
|
136
|
-
numbers = rand(100..999)
|
|
137
|
-
"#{letters}-#{numbers}"
|
|
138
|
-
end
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
### Account Number with Format
|
|
142
|
-
```ruby
|
|
143
|
-
ColumnAnonymizer::Anonymizer.register(:account_number) do
|
|
144
|
-
prefix = "ACC"
|
|
145
|
-
year = Time.now.year
|
|
146
|
-
sequence = rand(10000..99999)
|
|
147
|
-
"#{prefix}#{year}#{sequence}"
|
|
148
|
-
end
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
### Using Faker
|
|
152
|
-
```ruby
|
|
153
|
-
ColumnAnonymizer::Anonymizer.register(:company_name) do
|
|
154
|
-
Faker::Company.name
|
|
155
|
-
end
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
### From Database
|
|
159
|
-
```ruby
|
|
160
|
-
ColumnAnonymizer::Anonymizer.register(:department_name) do
|
|
161
|
-
Department.active.pluck(:name).sample || "General"
|
|
162
|
-
end
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
---
|
|
166
|
-
|
|
167
|
-
## 🔧 API Reference
|
|
168
|
-
|
|
169
|
-
### Register a Generator
|
|
170
|
-
```ruby
|
|
171
|
-
ColumnAnonymizer::Anonymizer.register(type, generator = nil, &block)
|
|
172
|
-
|
|
173
|
-
# With block
|
|
174
|
-
register(:type) { "value" }
|
|
175
|
-
|
|
176
|
-
# With lambda
|
|
177
|
-
register(:type, -> { "value" })
|
|
178
|
-
|
|
179
|
-
# With callable
|
|
180
|
-
register(:type, MyGenerator)
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
### Unregister a Generator
|
|
184
|
-
```ruby
|
|
185
|
-
ColumnAnonymizer::Anonymizer.unregister(:type)
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
### Check if Generator Exists
|
|
189
|
-
```ruby
|
|
190
|
-
ColumnAnonymizer::Anonymizer.generator_exists?(:type)
|
|
191
|
-
# => true/false
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
### Get All Generators
|
|
195
|
-
```ruby
|
|
196
|
-
ColumnAnonymizer::Anonymizer.all_generators
|
|
197
|
-
# => { email: #<Proc>, phone: #<Proc>, credit_card: #<Proc>, ... }
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
### Reset Custom Generators (Testing)
|
|
201
|
-
```ruby
|
|
202
|
-
ColumnAnonymizer::Anonymizer.reset_custom_generators!
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
## 🧪 How Custom Generators Merge
|
|
208
|
-
|
|
209
|
-
### Built-in Generators
|
|
210
|
-
```ruby
|
|
211
|
-
BUILT_IN_GENERATORS = {
|
|
212
|
-
email: -> { Faker::Internet.email },
|
|
213
|
-
phone: -> { Faker::PhoneNumber.phone_number },
|
|
214
|
-
ssn: -> { Faker::IdNumber.ssn_valid },
|
|
215
|
-
name: -> { Faker::Name.name },
|
|
216
|
-
first_name: -> { Faker::Name.first_name },
|
|
217
|
-
last_name: -> { Faker::Name.last_name },
|
|
218
|
-
address: -> { Faker::Address.full_address },
|
|
219
|
-
text: -> { Faker::Lorem.paragraph }
|
|
220
|
-
}
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
### Custom Generators
|
|
224
|
-
```ruby
|
|
225
|
-
@custom_generators = {
|
|
226
|
-
credit_card: -> { "XXXX-XXXX-XXXX-#{rand(1000..9999)}" },
|
|
227
|
-
employee_id: -> { "EMP-#{Time.now.year}-#{rand(10000..99999)}" }
|
|
228
|
-
}
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
### Merged (all_generators)
|
|
232
|
-
```ruby
|
|
233
|
-
{
|
|
234
|
-
# Built-ins
|
|
235
|
-
email: -> { ... },
|
|
236
|
-
phone: -> { ... },
|
|
237
|
-
ssn: -> { ... },
|
|
238
|
-
name: -> { ... },
|
|
239
|
-
first_name: -> { ... },
|
|
240
|
-
last_name: -> { ... },
|
|
241
|
-
address: -> { ... },
|
|
242
|
-
text: -> { ... },
|
|
243
|
-
|
|
244
|
-
# Custom
|
|
245
|
-
credit_card: -> { ... },
|
|
246
|
-
employee_id: -> { ... }
|
|
247
|
-
}
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
---
|
|
251
|
-
|
|
252
|
-
## 🔄 Complete Workflow
|
|
253
|
-
|
|
254
|
-
### 1. Setup
|
|
255
|
-
```bash
|
|
256
|
-
# Install gem
|
|
257
|
-
echo "gem 'column_anonymizer'" >> Gemfile
|
|
258
|
-
bundle install
|
|
259
|
-
|
|
260
|
-
# Generate config
|
|
261
|
-
rails g column_anonymizer:install --scan
|
|
262
|
-
|
|
263
|
-
# Generate initializer for custom types
|
|
264
|
-
rails g column_anonymizer:initializer
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
### 2. Define Custom Types
|
|
268
|
-
```ruby
|
|
269
|
-
# config/initializers/column_anonymizer.rb
|
|
270
|
-
|
|
271
|
-
ColumnAnonymizer::Anonymizer.register(:credit_card) do
|
|
272
|
-
"XXXX-XXXX-XXXX-#{rand(1000..9999)}"
|
|
273
|
-
end
|
|
274
|
-
|
|
275
|
-
ColumnAnonymizer::Anonymizer.register(:employee_id) do
|
|
276
|
-
"EMP-#{Time.now.year}-#{rand(10000..99999)}"
|
|
277
|
-
end
|
|
278
|
-
|
|
279
|
-
ColumnAnonymizer::Anonymizer.register(:medical_record) do
|
|
280
|
-
"MRN#{rand(100000..999999)}"
|
|
281
|
-
end
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
### 3. Configure YAML
|
|
285
|
-
```yaml
|
|
286
|
-
# config/encrypted_columns.yml
|
|
287
|
-
User:
|
|
288
|
-
email: email # Built-in
|
|
289
|
-
credit_card_number: credit_card # Custom!
|
|
290
|
-
|
|
291
|
-
Employee:
|
|
292
|
-
employee_number: employee_id # Custom!
|
|
293
|
-
ssn: ssn # Built-in
|
|
294
|
-
|
|
295
|
-
Patient:
|
|
296
|
-
medical_record_number: medical_record # Custom!
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
### 4. Use in Models
|
|
300
|
-
```ruby
|
|
301
|
-
class User < ApplicationRecord
|
|
302
|
-
encrypts :email
|
|
303
|
-
encrypts :credit_card_number
|
|
304
|
-
end
|
|
305
|
-
|
|
306
|
-
class Employee < ApplicationRecord
|
|
307
|
-
encrypts :employee_number
|
|
308
|
-
encrypts :ssn
|
|
309
|
-
end
|
|
310
|
-
|
|
311
|
-
class Patient < ApplicationRecord
|
|
312
|
-
encrypts :medical_record_number
|
|
313
|
-
end
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
### 5. Anonymize
|
|
317
|
-
```ruby
|
|
318
|
-
user = User.first
|
|
319
|
-
ColumnAnonymizer::Anonymizer.anonymize_model!(user)
|
|
320
|
-
|
|
321
|
-
# Before:
|
|
322
|
-
# email: "john@example.com"
|
|
323
|
-
# credit_card_number: "4532-1234-5678-9012"
|
|
324
|
-
|
|
325
|
-
# After:
|
|
326
|
-
# email: "user_abc123@example.com"
|
|
327
|
-
# credit_card_number: "XXXX-XXXX-XXXX-7482"
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
---
|
|
331
|
-
|
|
332
|
-
## ✨ Benefits
|
|
333
|
-
|
|
334
|
-
### Flexibility
|
|
335
|
-
- ✅ Define any custom format
|
|
336
|
-
- ✅ Use Faker, Rails models, or custom logic
|
|
337
|
-
- ✅ Domain-specific anonymization
|
|
338
|
-
|
|
339
|
-
### Simplicity
|
|
340
|
-
- ✅ Easy registration with blocks
|
|
341
|
-
- ✅ No complex class hierarchy
|
|
342
|
-
- ✅ Just define and use
|
|
343
|
-
|
|
344
|
-
### Power
|
|
345
|
-
- ✅ Access to full Ruby/Rails environment
|
|
346
|
-
- ✅ Can use database queries
|
|
347
|
-
- ✅ Can use external libraries
|
|
348
|
-
|
|
349
|
-
### Maintainability
|
|
350
|
-
- ✅ All custom types in one place (initializer)
|
|
351
|
-
- ✅ Easy to test
|
|
352
|
-
- ✅ Clear separation from built-ins
|
|
353
|
-
|
|
354
|
-
---
|
|
355
|
-
|
|
356
|
-
## 🧪 Testing
|
|
357
|
-
|
|
358
|
-
```ruby
|
|
359
|
-
# spec/initializers/column_anonymizer_spec.rb
|
|
360
|
-
|
|
361
|
-
RSpec.describe "Custom Anonymizers" do
|
|
362
|
-
before do
|
|
363
|
-
ColumnAnonymizer::Anonymizer.reset_custom_generators!
|
|
364
|
-
|
|
365
|
-
ColumnAnonymizer::Anonymizer.register(:credit_card) do
|
|
366
|
-
"XXXX-XXXX-XXXX-#{rand(1000..9999)}"
|
|
367
|
-
end
|
|
368
|
-
end
|
|
369
|
-
|
|
370
|
-
it "registers custom generator" do
|
|
371
|
-
expect(ColumnAnonymizer::Anonymizer.generator_exists?(:credit_card)).to be true
|
|
372
|
-
end
|
|
373
|
-
|
|
374
|
-
it "generates correct format" do
|
|
375
|
-
generator = ColumnAnonymizer::Anonymizer.all_generators[:credit_card]
|
|
376
|
-
result = generator.call
|
|
377
|
-
|
|
378
|
-
expect(result).to match(/^XXXX-XXXX-XXXX-\d{4}$/)
|
|
379
|
-
end
|
|
380
|
-
|
|
381
|
-
it "merges with built-in generators" do
|
|
382
|
-
generators = ColumnAnonymizer::Anonymizer.all_generators
|
|
383
|
-
|
|
384
|
-
expect(generators).to include(:email, :phone, :credit_card)
|
|
385
|
-
end
|
|
386
|
-
end
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
---
|
|
390
|
-
|
|
391
|
-
## 📊 Technical Implementation
|
|
392
|
-
|
|
393
|
-
### Class Structure
|
|
394
|
-
```ruby
|
|
395
|
-
class Anonymizer
|
|
396
|
-
# Built-in generators (frozen)
|
|
397
|
-
BUILT_IN_GENERATORS = { ... }.freeze
|
|
398
|
-
|
|
399
|
-
# Custom generators (mutable)
|
|
400
|
-
@custom_generators = {}
|
|
401
|
-
|
|
402
|
-
class << self
|
|
403
|
-
# Registration API
|
|
404
|
-
def register(type, generator = nil, &block)
|
|
405
|
-
# Store in @custom_generators
|
|
406
|
-
end
|
|
407
|
-
|
|
408
|
-
# Merge built-in + custom
|
|
409
|
-
def all_generators
|
|
410
|
-
BUILT_IN_GENERATORS.merge(@custom_generators)
|
|
411
|
-
end
|
|
412
|
-
|
|
413
|
-
# Use merged generators
|
|
414
|
-
def anonymize_model(model_instance)
|
|
415
|
-
generators = all_generators
|
|
416
|
-
# Use generators[column_type]
|
|
417
|
-
end
|
|
418
|
-
end
|
|
419
|
-
end
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
### Flow
|
|
423
|
-
```
|
|
424
|
-
1. Rails boots
|
|
425
|
-
2. Initializer loads (config/initializers/column_anonymizer.rb)
|
|
426
|
-
3. Custom generators registered via .register()
|
|
427
|
-
4. Stored in @custom_generators
|
|
428
|
-
5. When anonymizing:
|
|
429
|
-
- all_generators called
|
|
430
|
-
- BUILT_IN_GENERATORS.merge(@custom_generators)
|
|
431
|
-
- Merged hash used for anonymization
|
|
432
|
-
6. Custom types override built-ins if same key
|
|
433
|
-
```
|
|
434
|
-
|
|
435
|
-
---
|
|
436
|
-
|
|
437
|
-
## 📚 Documentation
|
|
438
|
-
|
|
439
|
-
### Created
|
|
440
|
-
1. **CUSTOM_GENERATORS_GUIDE.md** (500+ lines)
|
|
441
|
-
- Complete guide with examples
|
|
442
|
-
- All registration patterns
|
|
443
|
-
- Advanced use cases
|
|
444
|
-
- Best practices
|
|
445
|
-
- Troubleshooting
|
|
446
|
-
|
|
447
|
-
2. **CUSTOM_GENERATORS_QUICK_REF.md**
|
|
448
|
-
- One-page reference
|
|
449
|
-
- Common patterns
|
|
450
|
-
- API methods
|
|
451
|
-
- Quick examples
|
|
452
|
-
|
|
453
|
-
3. **README.md** - Updated
|
|
454
|
-
- Custom generators section
|
|
455
|
-
- Quick example
|
|
456
|
-
- Link to full guide
|
|
457
|
-
|
|
458
|
-
4. **CHANGELOG.md** - Updated
|
|
459
|
-
- Feature documented
|
|
460
|
-
- API listed
|
|
461
|
-
- Changes noted
|
|
462
|
-
|
|
463
|
-
---
|
|
464
|
-
|
|
465
|
-
## 🎉 Summary
|
|
466
|
-
|
|
467
|
-
You can now add custom anonymization types easily:
|
|
468
|
-
|
|
469
|
-
### Command
|
|
470
|
-
```bash
|
|
471
|
-
rails generate column_anonymizer:initializer
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
### Register
|
|
475
|
-
```ruby
|
|
476
|
-
ColumnAnonymizer::Anonymizer.register(:custom_type) do
|
|
477
|
-
# Your anonymization logic
|
|
478
|
-
end
|
|
479
|
-
```
|
|
480
|
-
|
|
481
|
-
### Use
|
|
482
|
-
```yaml
|
|
483
|
-
Model:
|
|
484
|
-
column: custom_type
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
**Simple, powerful, and flexible!** 🚀
|
|
488
|
-
|
|
489
|
-
---
|
|
490
|
-
|
|
491
|
-
## 📦 Files Summary
|
|
492
|
-
|
|
493
|
-
| File | Purpose |
|
|
494
|
-
|------|---------|
|
|
495
|
-
| `lib/column_anonymizer/anonymizer.rb` | Enhanced with registration API |
|
|
496
|
-
| `lib/generators/.../initializer_generator.rb` | Generator command |
|
|
497
|
-
| `lib/generators/.../templates/column_anonymizer.rb` | Template with examples |
|
|
498
|
-
| `CUSTOM_GENERATORS_GUIDE.md` | Complete documentation |
|
|
499
|
-
| `CUSTOM_GENERATORS_QUICK_REF.md` | Quick reference |
|
|
500
|
-
| `README.md` | Updated with custom generators |
|
|
501
|
-
| `CHANGELOG.md` | Feature documented |
|
|
502
|
-
|
|
503
|
-
---
|
|
504
|
-
|
|
505
|
-
**Status:** ✅ **COMPLETE AND READY TO USE**
|
|
506
|
-
**Date:** February 5, 2026
|
|
507
|
-
**Implementation:** Custom generator registration system
|