Module: Synthra::DeterministicIds
- Defined in:
- lib/synthra/deterministic_ids.rb
Overview
Deterministic ID Assignment
Generates stable, reproducible IDs based on context. Useful for testing and seeding where you need consistent IDs.
Constant Summary collapse
- NAMESPACE =
UUID namespace for Synthra (generated once, fixed)
"6ba7b810-9dad-11d1-80b4-00c04fd430c8"
Class Method Summary collapse
-
.batch(count, type: :uuid, variant: nil, seed: nil, **options) ⇒ Array<String|Integer>
Generate deterministic IDs for a batch.
- .build_input(variant, index, seed) ⇒ Object private
- .format_as_uuid(hash) ⇒ Object private
-
.integer(variant: nil, index: 0, seed: nil, max: 2_147_483_647) ⇒ Integer
Generate a deterministic integer ID.
-
.short_id(variant: nil, index: 0, seed: nil, length: 11) ⇒ String
Generate a deterministic short ID (like YouTube IDs).
-
.slug(variant: nil, index: 0, seed: nil, words: 3) ⇒ String
Generate a deterministic slug.
-
.uuid(variant: nil, index: 0, seed: nil) ⇒ String
Generate a deterministic UUID.
Class Method Details
.batch(count, type: :uuid, variant: nil, seed: nil, **options) ⇒ Array<String|Integer>
Generate deterministic IDs for a batch
117 118 119 120 121 |
# File 'lib/synthra/deterministic_ids.rb', line 117 def batch(count, type: :uuid, variant: nil, seed: nil, **) count.times.map do |i| send(type, variant: variant, index: i, seed: seed, **) end end |
.build_input(variant, index, seed) ⇒ Object (private)
125 126 127 128 129 130 131 |
# File 'lib/synthra/deterministic_ids.rb', line 125 def build_input(variant, index, seed) parts = [NAMESPACE] parts << variant.to_s if variant parts << index.to_s parts << seed.to_s if seed parts.join("-") end |
.format_as_uuid(hash) ⇒ Object (private)
133 134 135 136 137 138 |
# File 'lib/synthra/deterministic_ids.rb', line 133 def format_as_uuid(hash) # RFC 4122 v4: the leading "4" sets the version nibble; the 17th nibble must encode variant # 10xx (i.e. 8/9/a/b) or strict UUID validators reject it. Mask hash[16] into that range. variant = ((hash[16].to_i(16) & 0x3) | 0x8).to_s(16) "#{hash[0, 8]}-#{hash[8, 4]}-4#{hash[13, 3]}-#{variant}#{hash[17, 3]}-#{hash[20, 12]}" end |
.integer(variant: nil, index: 0, seed: nil, max: 2_147_483_647) ⇒ Integer
Generate a deterministic integer ID
51 52 53 54 55 56 57 |
# File 'lib/synthra/deterministic_ids.rb', line 51 def integer(variant: nil, index: 0, seed: nil, max: 2_147_483_647) input = build_input(variant, index, seed) hash = Digest::MD5.hexdigest(input) # Convert first 8 bytes to integer hash[0, 16].to_i(16) % max end |
.short_id(variant: nil, index: 0, seed: nil, length: 11) ⇒ String
Generate a deterministic short ID (like YouTube IDs)
67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/synthra/deterministic_ids.rb', line 67 def short_id(variant: nil, index: 0, seed: nil, length: 11) alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" input = build_input(variant, index, seed) hash = Digest::SHA256.hexdigest(input) result = +"" length.times do |i| byte = hash[(i * 2), 2].to_i(16) result << alphabet[byte % alphabet.length] end result end |
.slug(variant: nil, index: 0, seed: nil, words: 3) ⇒ String
Generate a deterministic slug
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/synthra/deterministic_ids.rb', line 89 def slug(variant: nil, index: 0, seed: nil, words: 3) word_list = %w[ alpha beta gamma delta epsilon zeta eta theta iota kappa lambda mu nu xi omicron pi rho sigma tau upsilon able baker charlie delta echo foxtrot golf hotel india juliet quick brown fox jumps over lazy dog hello world test ] input = build_input(variant, index, seed) hash = Digest::SHA256.hexdigest(input) selected = [] words.times do |i| byte = hash[(i * 2), 2].to_i(16) selected << word_list[byte % word_list.length] end selected.join("-") end |
.uuid(variant: nil, index: 0, seed: nil) ⇒ String
Generate a deterministic UUID
35 36 37 38 39 40 41 |
# File 'lib/synthra/deterministic_ids.rb', line 35 def uuid(variant: nil, index: 0, seed: nil) input = build_input(variant, index, seed) hash = Digest::SHA256.hexdigest(input) # Format as UUID v4 format_as_uuid(hash) end |