Last active
April 27, 2017 08:25
-
-
Save kylewelsby/9c596c875b4ed16b6b77bc3501aaea30 to your computer and use it in GitHub Desktop.
The ability to generate an ULID from a legacy integer ID. Useful for syncing data between systems.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'time' | |
class User | |
def id | |
'507f1f77bcf86cd799439011' | |
end | |
def created_at | |
Time.parse('2017-04-24 12:15:20 +0200') | |
end | |
end | |
user = User.new | |
ulid = CustomULID.generate("Legacy::Ea2::#{user.class}", user.id, user.created_at) | |
puts ulid | |
ulid2 = CustomULID.generate("Legacy::Ea2::#{user.class}", user.id, user.created_at) | |
puts ulid2 | |
puts ulid == ulid2 | |
ulid3 = CustomULID.generate("Legacy::Ea2::#{user.class}", '507f191e810c19729de860ea', user.created_at) | |
puts ulid3 | |
puts ulid == ulid3 | |
puts CustomULID.generate("Legacy::Ea2::Person", '507f191e810c19729de860ea', user.created_at) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'digest/sha1' | |
class CustomULID | |
ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ' # Crockford's Base32 | |
RANDOM_BYTES = 10 | |
ENCODED_LENGTH = 26 | |
BIT_LENGTH = 128 | |
BITS_PER_B32_CHAR = 5 | |
MASK = 0x1f | |
def self.generate(class_name, id, created_at) | |
time = [(created_at.to_f * 10_000).to_i].pack("Q>")[2..-1] | |
word = [id, Digest::SHA1.hexdigest(class_name)].pack("a5a5") | |
bytes = (time + word) | |
(hi, lo) = bytes.unpack("Q>Q") | |
input = (hi << 64) | lo | |
(1..ENCODED_LENGTH).to_a.reduce("") do |s, n| | |
shift = BIT_LENGTH - BITS_PER_B32_CHAR * n | |
s + ENCODING[(input >> shift) & MASK] | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment