opaque_id 1.2.0 → 1.3.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.
@@ -0,0 +1,17 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32">
2
+ <defs>
3
+ <linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#a855f7;stop-opacity:1" />
5
+ <stop offset="100%" style="stop-color:#c084fc;stop-opacity:1" />
6
+ </linearGradient>
7
+ </defs>
8
+
9
+ <!-- Background circle -->
10
+ <circle cx="16" cy="16" r="15" fill="#0a0a0a" stroke="url(#gradient)" stroke-width="2"/>
11
+
12
+ <!-- Letter O -->
13
+ <circle cx="16" cy="16" r="8" fill="none" stroke="url(#gradient)" stroke-width="2.5"/>
14
+
15
+ <!-- Inner dot -->
16
+ <circle cx="16" cy="16" r="3" fill="url(#gradient)"/>
17
+ </svg>
@@ -0,0 +1,65 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 630" width="1200" height="630">
2
+ <defs>
3
+ <linearGradient id="bgGradient" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#0a0a0a;stop-opacity:1" />
5
+ <stop offset="100%" style="stop-color:#1a1a1a;stop-opacity:1" />
6
+ </linearGradient>
7
+ <linearGradient id="textGradient" x1="0%" y1="0%" x2="100%" y2="0%">
8
+ <stop offset="0%" style="stop-color:#a855f7;stop-opacity:1" />
9
+ <stop offset="100%" style="stop-color:#c084fc;stop-opacity:1" />
10
+ </linearGradient>
11
+ </defs>
12
+
13
+ <!-- Background -->
14
+ <rect width="1200" height="630" fill="url(#bgGradient)"/>
15
+
16
+ <!-- Logo -->
17
+ <circle cx="150" cy="150" r="60" fill="none" stroke="url(#textGradient)" stroke-width="8"/>
18
+ <circle cx="150" cy="150" r="25" fill="url(#textGradient)"/>
19
+
20
+ <!-- Title -->
21
+ <text x="300" y="180" font-family="Arial, sans-serif" font-size="72" font-weight="bold" fill="url(#textGradient)">
22
+ OpaqueId
23
+ </text>
24
+
25
+ <!-- Subtitle -->
26
+ <text x="300" y="240" font-family="Arial, sans-serif" font-size="32" fill="#e0e0e0">
27
+ Documentation
28
+ </text>
29
+
30
+ <!-- Description -->
31
+ <text x="300" y="320" font-family="Arial, sans-serif" font-size="24" fill="#b0b0b0">
32
+ Generate cryptographically secure, collision-free opaque IDs
33
+ </text>
34
+ <text x="300" y="360" font-family="Arial, sans-serif" font-size="24" fill="#b0b0b0">
35
+ for ActiveRecord models
36
+ </text>
37
+
38
+ <!-- Features -->
39
+ <text x="300" y="420" font-family="Arial, sans-serif" font-size="18" fill="#808080">
40
+ • High Performance • Rails Integration • Secure Generation
41
+ </text>
42
+
43
+ <!-- URL -->
44
+ <text x="300" y="480" font-family="Arial, sans-serif" font-size="20" fill="#a855f7">
45
+ nyaggah.github.io/opaque_id
46
+ </text>
47
+
48
+ <!-- Code example -->
49
+ <rect x="800" y="200" width="350" height="200" fill="#1a1a1a" stroke="#333333" stroke-width="2" rx="8"/>
50
+ <text x="820" y="230" font-family="Monaco, monospace" font-size="16" fill="#e0e0e0">
51
+ class User &lt; ApplicationRecord
52
+ </text>
53
+ <text x="820" y="260" font-family="Monaco, monospace" font-size="16" fill="#e0e0e0">
54
+ include OpaqueId::Model
55
+ </text>
56
+ <text x="820" y="290" font-family="Monaco, monospace" font-size="16" fill="#e0e0e0">
57
+ end
58
+ </text>
59
+ <text x="820" y="330" font-family="Monaco, monospace" font-size="16" fill="#a855f7">
60
+ # user.opaque_id
61
+ </text>
62
+ <text x="820" y="360" font-family="Monaco, monospace" font-size="16" fill="#10b981">
63
+ # =&gt; "V1StGXR8_Z5jdHi6B-myT"
64
+ </text>
65
+ </svg>
@@ -0,0 +1,548 @@
1
+ ---
2
+ layout: default
3
+ title: Configuration
4
+ nav_order: 5
5
+ description: "Complete configuration guide with all options and examples"
6
+ permalink: /configuration/
7
+ ---
8
+
9
+ # Configuration
10
+
11
+ OpaqueId provides extensive configuration options to customize ID generation for your specific needs. This guide covers all available configuration options with practical examples.
12
+
13
+ ## Model-Level Configuration
14
+
15
+ Configure OpaqueId on a per-model basis using class-level settings.
16
+
17
+ ### Basic Configuration
18
+
19
+ ```ruby
20
+ class User < ApplicationRecord
21
+ include OpaqueId::Model
22
+
23
+ # Custom column name
24
+ self.opaque_id_column = :public_id
25
+
26
+ # Custom length (default: 21)
27
+ self.opaque_id_length = 15
28
+
29
+ # Custom alphabet (default: ALPHANUMERIC_ALPHABET)
30
+ self.opaque_id_alphabet = OpaqueId::STANDARD_ALPHABET
31
+
32
+ # Require letter start (default: false)
33
+ self.opaque_id_require_letter_start = true
34
+
35
+ # Max retry attempts (default: 3)
36
+ self.opaque_id_max_retry = 5
37
+
38
+ # Characters to purge from generated IDs (default: [])
39
+ self.opaque_id_purge_chars = ['0', 'O', 'l', 'I']
40
+ end
41
+ ```
42
+
43
+ ### Configuration Options Reference
44
+
45
+ | Option | Type | Default | Description |
46
+ | -------------------------------- | ------- | ----------------------- | --------------------------------------------- |
47
+ | `opaque_id_column` | Symbol | `:opaque_id` | Column name for storing the opaque ID |
48
+ | `opaque_id_length` | Integer | `21` | Length of generated IDs |
49
+ | `opaque_id_alphabet` | String | `ALPHANUMERIC_ALPHABET` | Character set for ID generation |
50
+ | `opaque_id_require_letter_start` | Boolean | `false` | Require IDs to start with a letter |
51
+ | `opaque_id_max_retry` | Integer | `3` | Maximum retry attempts for collision handling |
52
+ | `opaque_id_purge_chars` | Array | `[]` | Characters to exclude from generated IDs |
53
+
54
+ ## Global Configuration
55
+
56
+ Configure OpaqueId globally using an initializer.
57
+
58
+ ### Basic Global Configuration
59
+
60
+ ```ruby
61
+ # config/initializers/opaque_id.rb
62
+ OpaqueId.configure do |config|
63
+ config.default_length = 15
64
+ config.default_alphabet = OpaqueId::STANDARD_ALPHABET
65
+ end
66
+ ```
67
+
68
+ ### Advanced Global Configuration
69
+
70
+ ```ruby
71
+ # config/initializers/opaque_id.rb
72
+ OpaqueId.configure do |config|
73
+ # Set default values for all models
74
+ config.default_length = 21
75
+ config.default_alphabet = OpaqueId::ALPHANUMERIC_ALPHABET
76
+
77
+ # Configure specific models
78
+ config.models = {
79
+ 'User' => {
80
+ length: 15,
81
+ alphabet: OpaqueId::STANDARD_ALPHABET,
82
+ require_letter_start: true
83
+ },
84
+ 'Order' => {
85
+ length: 12,
86
+ alphabet: OpaqueId::ALPHANUMERIC_ALPHABET,
87
+ column: :public_id
88
+ }
89
+ }
90
+ end
91
+ ```
92
+
93
+ ## Alphabet Configuration
94
+
95
+ ### Built-in Alphabets
96
+
97
+ #### ALPHANUMERIC_ALPHABET (Default)
98
+
99
+ ```ruby
100
+ # Characters: A-Z, a-z, 0-9 (62 characters)
101
+ # Use case: General purpose, URL-safe
102
+ # Example output: "V1StGXR8_Z5jdHi6B-myT"
103
+
104
+ class User < ApplicationRecord
105
+ include OpaqueId::Model
106
+ self.opaque_id_alphabet = OpaqueId::ALPHANUMERIC_ALPHABET
107
+ end
108
+ ```
109
+
110
+ #### STANDARD_ALPHABET
111
+
112
+ ```ruby
113
+ # Characters: A-Z, a-z, 0-9, -, _ (64 characters)
114
+ # Use case: Fastest generation, URL-safe
115
+ # Example output: "V1StGXR8_Z5jdHi6B-myT"
116
+
117
+ class User < ApplicationRecord
118
+ include OpaqueId::Model
119
+ self.opaque_id_alphabet = OpaqueId::STANDARD_ALPHABET
120
+ end
121
+ ```
122
+
123
+ ### Custom Alphabets
124
+
125
+ #### Numeric Only
126
+
127
+ ```ruby
128
+ class Order < ApplicationRecord
129
+ include OpaqueId::Model
130
+
131
+ # Generate numeric-only IDs
132
+ self.opaque_id_alphabet = "0123456789"
133
+ self.opaque_id_length = 10
134
+ end
135
+
136
+ # Example output: "1234567890"
137
+ ```
138
+
139
+ #### Hexadecimal
140
+
141
+ ```ruby
142
+ class ApiKey < ApplicationRecord
143
+ include OpaqueId::Model
144
+
145
+ # Generate hexadecimal IDs
146
+ self.opaque_id_alphabet = "0123456789abcdef"
147
+ self.opaque_id_length = 16
148
+ end
149
+
150
+ # Example output: "a1b2c3d4e5f67890"
151
+ ```
152
+
153
+ #### URL-Safe Characters
154
+
155
+ ```ruby
156
+ class Article < ApplicationRecord
157
+ include OpaqueId::Model
158
+
159
+ # Generate URL-safe IDs
160
+ self.opaque_id_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
161
+ self.opaque_id_length = 8
162
+ end
163
+
164
+ # Example output: "V1StGXR8"
165
+ ```
166
+
167
+ #### Base64-Style
168
+
169
+ ```ruby
170
+ class Document < ApplicationRecord
171
+ include OpaqueId::Model
172
+
173
+ # Generate Base64-style IDs
174
+ self.opaque_id_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
175
+ self.opaque_id_length = 12
176
+ end
177
+
178
+ # Example output: "V1StGXR8_Z5j"
179
+ ```
180
+
181
+ ## Length Configuration
182
+
183
+ ### Short IDs (8-12 characters)
184
+
185
+ ```ruby
186
+ class ShortUrl < ApplicationRecord
187
+ include OpaqueId::Model
188
+
189
+ # Short IDs for URLs
190
+ self.opaque_id_length = 8
191
+ self.opaque_id_alphabet = OpaqueId::ALPHANUMERIC_ALPHABET
192
+ end
193
+
194
+ # Example output: "V1StGXR8"
195
+ ```
196
+
197
+ ### Medium IDs (15-21 characters)
198
+
199
+ ```ruby
200
+ class User < ApplicationRecord
201
+ include OpaqueId::Model
202
+
203
+ # Standard length for general use
204
+ self.opaque_id_length = 21
205
+ self.opaque_id_alphabet = OpaqueId::ALPHANUMERIC_ALPHABET
206
+ end
207
+
208
+ # Example output: "V1StGXR8_Z5jdHi6B-myT"
209
+ ```
210
+
211
+ ### Long IDs (32+ characters)
212
+
213
+ ```ruby
214
+ class ApiKey < ApplicationRecord
215
+ include OpaqueId::Model
216
+
217
+ # Long IDs for sensitive data
218
+ self.opaque_id_length = 32
219
+ self.opaque_id_alphabet = OpaqueId::STANDARD_ALPHABET
220
+ end
221
+
222
+ # Example output: "V1StGXR8_Z5jdHi6B-myT1234567890"
223
+ ```
224
+
225
+ ## Column Name Configuration
226
+
227
+ ### Custom Column Names
228
+
229
+ ```ruby
230
+ class User < ApplicationRecord
231
+ include OpaqueId::Model
232
+
233
+ # Use a different column name
234
+ self.opaque_id_column = :public_id
235
+ end
236
+
237
+ # Now the methods use the custom column name
238
+ user = User.create!(name: "John Doe")
239
+ puts user.public_id
240
+ # => "V1StGXR8_Z5jdHi6B-myT"
241
+
242
+ user = User.find_by_public_id("V1StGXR8_Z5jdHi6B-myT")
243
+ ```
244
+
245
+ ### Multiple Column Names
246
+
247
+ ```ruby
248
+ class User < ApplicationRecord
249
+ include OpaqueId::Model
250
+ self.opaque_id_column = :public_id
251
+ end
252
+
253
+ class Order < ApplicationRecord
254
+ include OpaqueId::Model
255
+ self.opaque_id_column = :order_number
256
+ end
257
+
258
+ class Product < ApplicationRecord
259
+ include OpaqueId::Model
260
+ self.opaque_id_column = :sku
261
+ end
262
+ ```
263
+
264
+ ## Validation Configuration
265
+
266
+ ### Letter Start Requirement
267
+
268
+ ```ruby
269
+ class User < ApplicationRecord
270
+ include OpaqueId::Model
271
+
272
+ # Require IDs to start with a letter
273
+ self.opaque_id_require_letter_start = true
274
+ end
275
+
276
+ # This will retry until it generates an ID starting with a letter
277
+ user = User.create!(name: "John Doe")
278
+ puts user.opaque_id
279
+ # => "V1StGXR8_Z5jdHi6B-myT" (starts with 'V')
280
+ ```
281
+
282
+ ### Character Purging
283
+
284
+ ```ruby
285
+ class User < ApplicationRecord
286
+ include OpaqueId::Model
287
+
288
+ # Exclude confusing characters
289
+ self.opaque_id_purge_chars = ['0', 'O', 'l', 'I']
290
+ end
291
+
292
+ # Generated IDs will not contain these characters
293
+ user = User.create!(name: "John Doe")
294
+ puts user.opaque_id
295
+ # => "V1StGXR8_Z5jdHi6B-myT" (no '0', 'O', 'l', 'I')
296
+ ```
297
+
298
+ ## Collision Handling Configuration
299
+
300
+ ### Retry Attempts
301
+
302
+ ```ruby
303
+ class User < ApplicationRecord
304
+ include OpaqueId::Model
305
+
306
+ # Increase retry attempts for high-volume applications
307
+ self.opaque_id_max_retry = 10
308
+ end
309
+ ```
310
+
311
+ ### Custom Collision Handling
312
+
313
+ ```ruby
314
+ class User < ApplicationRecord
315
+ include OpaqueId::Model
316
+
317
+ private
318
+
319
+ def set_opaque_id
320
+ retries = 0
321
+ max_retries = opaque_id_max_retry
322
+
323
+ begin
324
+ self.opaque_id = generate_opaque_id
325
+ rescue OpaqueId::GenerationError => e
326
+ retries += 1
327
+ if retries < max_retries
328
+ retry
329
+ else
330
+ # Custom fallback logic
331
+ self.opaque_id = generate_fallback_id
332
+ end
333
+ end
334
+ end
335
+
336
+ def generate_fallback_id
337
+ # Fallback generation method
338
+ "fallback_#{SecureRandom.hex(10)}"
339
+ end
340
+ end
341
+ ```
342
+
343
+ ## Environment-Specific Configuration
344
+
345
+ ### Development Environment
346
+
347
+ ```ruby
348
+ # config/environments/development.rb
349
+ if Rails.env.development?
350
+ OpaqueId.configure do |config|
351
+ # Shorter IDs for development
352
+ config.default_length = 8
353
+ config.default_alphabet = OpaqueId::ALPHANUMERIC_ALPHABET
354
+ end
355
+ end
356
+ ```
357
+
358
+ ### Production Environment
359
+
360
+ ```ruby
361
+ # config/environments/production.rb
362
+ if Rails.env.production?
363
+ OpaqueId.configure do |config|
364
+ # Longer IDs for production
365
+ config.default_length = 21
366
+ config.default_alphabet = OpaqueId::STANDARD_ALPHABET
367
+ end
368
+ end
369
+ ```
370
+
371
+ ### Test Environment
372
+
373
+ ```ruby
374
+ # config/environments/test.rb
375
+ if Rails.env.test?
376
+ OpaqueId.configure do |config|
377
+ # Predictable IDs for testing
378
+ config.default_length = 10
379
+ config.default_alphabet = "0123456789"
380
+ end
381
+ end
382
+ ```
383
+
384
+ ## Configuration Examples by Use Case
385
+
386
+ ### E-commerce Application
387
+
388
+ ```ruby
389
+ # Orders - short, numeric IDs
390
+ class Order < ApplicationRecord
391
+ include OpaqueId::Model
392
+
393
+ self.opaque_id_column = :order_number
394
+ self.opaque_id_length = 8
395
+ self.opaque_id_alphabet = "0123456789"
396
+ end
397
+
398
+ # Products - medium, alphanumeric IDs
399
+ class Product < ApplicationRecord
400
+ include OpaqueId::Model
401
+
402
+ self.opaque_id_column = :sku
403
+ self.opaque_id_length = 12
404
+ self.opaque_id_alphabet = OpaqueId::ALPHANUMERIC_ALPHABET
405
+ end
406
+
407
+ # Users - standard IDs
408
+ class User < ApplicationRecord
409
+ include OpaqueId::Model
410
+
411
+ self.opaque_id_length = 21
412
+ self.opaque_id_alphabet = OpaqueId::STANDARD_ALPHABET
413
+ end
414
+ ```
415
+
416
+ ### API Development
417
+
418
+ ```ruby
419
+ # API Keys - long, secure IDs
420
+ class ApiKey < ApplicationRecord
421
+ include OpaqueId::Model
422
+
423
+ self.opaque_id_length = 32
424
+ self.opaque_id_alphabet = OpaqueId::STANDARD_ALPHABET
425
+ self.opaque_id_require_letter_start = true
426
+ end
427
+
428
+ # API Tokens - medium, URL-safe IDs
429
+ class ApiToken < ApplicationRecord
430
+ include OpaqueId::Model
431
+
432
+ self.opaque_id_column = :token
433
+ self.opaque_id_length = 24
434
+ self.opaque_id_alphabet = OpaqueId::ALPHANUMERIC_ALPHABET
435
+ end
436
+ ```
437
+
438
+ ### Content Management
439
+
440
+ ```ruby
441
+ # Articles - short, URL-friendly IDs
442
+ class Article < ApplicationRecord
443
+ include OpaqueId::Model
444
+
445
+ self.opaque_id_column = :slug
446
+ self.opaque_id_length = 8
447
+ self.opaque_id_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
448
+ end
449
+
450
+ # Comments - standard IDs
451
+ class Comment < ApplicationRecord
452
+ include OpaqueId::Model
453
+
454
+ self.opaque_id_length = 15
455
+ self.opaque_id_alphabet = OpaqueId::ALPHANUMERIC_ALPHABET
456
+ end
457
+ ```
458
+
459
+ ## Configuration Validation
460
+
461
+ ### Validate Configuration
462
+
463
+ ```ruby
464
+ class User < ApplicationRecord
465
+ include OpaqueId::Model
466
+
467
+ validate :validate_opaque_id_configuration
468
+
469
+ private
470
+
471
+ def validate_opaque_id_configuration
472
+ if opaque_id_length < 8
473
+ errors.add(:base, "Opaque ID length must be at least 8 characters")
474
+ end
475
+
476
+ if opaque_id_alphabet.size < 16
477
+ errors.add(:base, "Opaque ID alphabet must have at least 16 characters")
478
+ end
479
+
480
+ if opaque_id_max_retry < 1
481
+ errors.add(:base, "Opaque ID max retry must be at least 1")
482
+ end
483
+ end
484
+ end
485
+ ```
486
+
487
+ ### Configuration Testing
488
+
489
+ ```ruby
490
+ # test/models/user_test.rb
491
+ class UserTest < ActiveSupport::TestCase
492
+ test "opaque_id configuration is valid" do
493
+ user = User.new(name: "Test User")
494
+
495
+ assert user.valid?
496
+ assert_equal 21, user.class.opaque_id_length
497
+ assert_equal OpaqueId::ALPHANUMERIC_ALPHABET, user.class.opaque_id_alphabet
498
+ end
499
+
500
+ test "opaque_id generation works with custom configuration" do
501
+ user = User.new(name: "Test User")
502
+ user.class.opaque_id_length = 15
503
+ user.class.opaque_id_alphabet = OpaqueId::STANDARD_ALPHABET
504
+
505
+ user.save!
506
+
507
+ assert_equal 15, user.opaque_id.length
508
+ assert user.opaque_id.match?(/\A[A-Za-z0-9_-]+\z/)
509
+ end
510
+ end
511
+ ```
512
+
513
+ ## Best Practices
514
+
515
+ ### 1. Choose Appropriate Length
516
+
517
+ - **Short IDs (8-12)**: Public URLs, user-facing identifiers
518
+ - **Medium IDs (15-21)**: General purpose, internal references
519
+ - **Long IDs (32+)**: Sensitive data, API keys, tokens
520
+
521
+ ### 2. Select Suitable Alphabets
522
+
523
+ - **ALPHANUMERIC_ALPHABET**: General purpose, URL-safe
524
+ - **STANDARD_ALPHABET**: Fastest generation, URL-safe
525
+ - **Custom alphabets**: Specific requirements (numeric, hexadecimal, etc.)
526
+
527
+ ### 3. Configure Collision Handling
528
+
529
+ - **Low volume**: Default retry attempts (3)
530
+ - **High volume**: Increase retry attempts (5-10)
531
+ - **Critical systems**: Implement custom fallback logic
532
+
533
+ ### 4. Use Environment-Specific Settings
534
+
535
+ - **Development**: Shorter IDs for easier testing
536
+ - **Production**: Longer IDs for better security
537
+ - **Test**: Predictable IDs for consistent testing
538
+
539
+ ## Next Steps
540
+
541
+ Now that you understand configuration options:
542
+
543
+ 1. **Explore [Alphabets](alphabets.md)** for detailed alphabet information
544
+ 2. **Check out [Use Cases](use-cases.md)** for real-world configuration examples
545
+ 3. **Review [Performance](performance.md)** for configuration optimization tips
546
+ 4. **Read [API Reference](api-reference.md)** for complete configuration documentation
547
+ 5. **Learn about [Algorithms](algorithms.md)** for technical implementation details
548
+ 6. **Understand [Security](security.md)** for security considerations