Extract hex_to_base36 and base36_to_hex methods in Uuid type

replacing normalize_base36. This should make it easier to convert
UUIDs between hex and base36 formats, useful when debugging production
logs that contain hex UUIDs.

For example, if in a log you see:

    User Load (0.3ms) SELECT `users`.* FROM `users` WHERE
    `users`.`account_id` = x'019afab815897a4f920f3a24fab75400' AND
    `users`.`id` = x'019afab815a2790688c58c7f8326e700' LIMIT 1

and you want to find that account or that user in the console, you can
now do:

    id = ActiveRecord::Type::Uuid.hex_to_base36("019afab815897a4f920f3a24fab75400")
    => "03f6bilrvt3oghzhurll4pp8g"
This commit is contained in:
Mike Dalessio
2025-12-08 10:05:03 -05:00
parent bf6ddcb933
commit 18b3319a94
2 changed files with 16 additions and 15 deletions
+15 -13
View File
@@ -4,32 +4,34 @@ module ActiveRecord
class Uuid < Binary class Uuid < Binary
BASE36_LENGTH = 25 # 36^25 > 2^128 BASE36_LENGTH = 25 # 36^25 > 2^128
def self.generate class << self
uuid = SecureRandom.uuid_v7 def generate
hex = uuid.delete("-") uuid = SecureRandom.uuid_v7
normalize_base36(hex.to_i(16)) hex = uuid.delete("-")
end hex_to_base36(hex)
end
def self.normalize_base36(integer) def hex_to_base36(hex)
integer.to_s(36).rjust(BASE36_LENGTH, "0") hex.to_i(16).to_s(36).rjust(BASE36_LENGTH, "0")
end
def base36_to_hex(base36)
base36.to_s.to_i(36).to_s(16).rjust(32, "0")
end
end end
def serialize(value) def serialize(value)
return unless value return unless value
binary = hex(value).scan(/../).map(&:hex).pack("C*") binary = Uuid.base36_to_hex(value).scan(/../).map(&:hex).pack("C*")
super(binary) super(binary)
end end
def hex(value)
value.to_s.to_i(36).to_s(16).rjust(32, "0")
end
def deserialize(value) def deserialize(value)
return unless value return unless value
hex = value.to_s.unpack1("H*") hex = value.to_s.unpack1("H*")
Uuid.normalize_base36(hex.to_i(16)) Uuid.hex_to_base36(hex)
end end
def cast(value) def cast(value)
+1 -2
View File
@@ -154,8 +154,7 @@ module FixturesTestHelper
# Format as UUID string and convert to base36 (25 chars) # Format as UUID string and convert to base36 (25 chars)
uuid = "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" % bytes uuid = "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" % bytes
hex = uuid.delete("-") ActiveRecord::Type::Uuid.hex_to_base36(uuid.delete("-"))
hex.to_i(16).to_s(36).rjust(25, "0")
end end
end end
end end