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.
- checksums.yaml +4 -4
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +28 -0
- data/CODE_OF_CONDUCT.md +11 -11
- data/README.md +82 -0
- data/docs/.gitignore +5 -0
- data/docs/404.html +25 -0
- data/docs/Gemfile +31 -0
- data/docs/Gemfile.lock +335 -0
- data/docs/_config.yml +162 -0
- data/docs/_data/navigation.yml +132 -0
- data/docs/_includes/footer_custom.html +8 -0
- data/docs/_includes/head_custom.html +67 -0
- data/docs/algorithms.md +409 -0
- data/docs/alphabets.md +521 -0
- data/docs/api-reference.md +594 -0
- data/docs/assets/css/custom.scss +798 -0
- data/docs/assets/images/favicon.svg +17 -0
- data/docs/assets/images/og-image.svg +65 -0
- data/docs/configuration.md +548 -0
- data/docs/development.md +567 -0
- data/docs/getting-started.md +256 -0
- data/docs/index.md +132 -0
- data/docs/installation.md +377 -0
- data/docs/performance.md +488 -0
- data/docs/robots.txt +11 -0
- data/docs/security.md +598 -0
- data/docs/usage.md +414 -0
- data/docs/use-cases.md +569 -0
- data/lib/opaque_id/version.rb +1 -1
- data/tasks/0003-prd-documentation-site.md +191 -0
- data/tasks/tasks-0003-prd-documentation-site.md +84 -0
- metadata +27 -2
- data/sig/opaque_id.rbs +0 -4
@@ -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 < 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
|
+
# => "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
|