Generating a CUID (Collision-resistant Unique Identifier) in Ruby involves using techniques such as the current timestamp, a counter, a machine fingerprint, and randomness. Below is an example implementation of generating a CUID in Ruby.
Steps to Generate a CUID in Ruby
- Timestamp: Get the current timestamp in milliseconds.
- Counter: Use a counter to handle multiple CUIDs generated in a short period.
- Fingerprint: Generate a machine-specific fingerprint.
- Randomness: Add random characters to further reduce the risk of collisions.
- Base36 Encoding: Encode the components using Base36 for readability.
Example Code
Here's a Ruby implementation to generate a CUID:
require 'digest/md5'
class CUIDGenerator
BASE36_CHARS = '0123456789abcdefghijklmnopqrstuvwxyz'.chars.freeze
@@counter = 0
@@last_timestamp = 0
def self.generate_cuid
timestamp = (Time.now.to_f * 1000).to_i
if timestamp == @@last_timestamp
@@counter += 1
else
@@last_timestamp = timestamp
@@counter = 0
end
timestamp_base36 = encode_base36(timestamp)
counter_base36 = encode_base36(@@counter)
fingerprint = get_machine_fingerprint
random_string = get_random_string(4)
"c#{timestamp_base36}#{counter_base36}#{fingerprint}#{random_string}"
end
private
def self.encode_base36(value)
return '0' if value == 0
result = ''
while value > 0
result = BASE36_CHARS[value % 36] + result
value /= 36
end
result
end
def self.get_machine_fingerprint
begin
hostname = `hostname`.strip
hash_value = Digest::MD5.hexdigest(hostname)
hash_value[0..3]
rescue
'0000'
end
end
def self.get_random_string(length)
Array.new(length) { BASE36_CHARS.sample }.join
end
end
# Example usage
puts CUIDGenerator.generate_cuid
Explanation
Base36 Encoding:
- The
encode_base36
method converts a number to a Base36 encoded string.
- The
Timestamp:
timestamp = (Time.now.to_f * 1000).to_i
gets the current timestamp in milliseconds.
Counter:
- A class-level counter (
@@counter
) is used to handle multiple CUIDs generated within the same millisecond. It is incremented and reset as necessary.
- A class-level counter (
Machine Fingerprint:
get_machine_fingerprint
fetches the machine's hostname, computes an MD5 hash, and returns the first 4 characters.
Random String:
get_random_string
generates a random string of specified length using Base36 characters.
Combine Components:
- The
generate_cuid
method combines the timestamp, counter, fingerprint, and random parts to form the final CUID.
- The
Summary
This Ruby implementation of CUID generation uses standard libraries (Digest::MD5
for hashing, Time
for timestamps, and basic string operations) to handle timestamps, hashing, randomness, and counters. This approach ensures that the generated CUIDs are unique, readable, and collision-resistant, suitable for various applications. Adjustments can be made based on specific requirements, such as error handling when fetching the machine's hostname or modifying the length of the random string portion.