Last active
January 16, 2026 00:47
-
-
Save joncode/a39791fdcdd7c19a695e3e6e7af16d7e to your computer and use it in GitHub Desktop.
HexIdMethods: secure, prefix-based IDs for ActiveRecord models for WEB2
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
| # WEB2 Secure Random ID generator | |
| # app/models/concerns/hex_id_methods.rb | |
| # include HexIdMethods in any model that uses :hex_id | |
| module HexIdMethods | |
| extend ActiveSupport::Concern | |
| # Create a safe character set: a-k, m-z, 0, 2-9 (no l, 1) - 34 characters | |
| SAFE_CHARS = (('a'..'k').to_a + ('m'..'z').to_a + ['0'] + ('2'..'9').to_a).freeze | |
| MAX_RETRIES = 3 | |
| included do | |
| before_validation :generate_hex_id, on: :create | |
| validates :hex_id, presence: true, uniqueness: true | |
| around_create :retry_on_hex_id_collision | |
| end | |
| private | |
| def generate_hex_id | |
| return if hex_id.present? | |
| self.hex_id = build_hex_id | |
| end | |
| def build_hex_id | |
| "#{hex_id_prefix}_#{secure_random_safe_string}" | |
| end | |
| def hex_id_prefix | |
| self.class.const_get(:HEX_ID_PREFIX) | |
| rescue NameError | |
| raise "Missing HEX_ID_PREFIX in #{self.class.name}" | |
| end | |
| def retry_on_hex_id_collision | |
| retries = 0 | |
| begin | |
| yield | |
| rescue ActiveRecord::RecordNotUnique | |
| raise if (retries += 1) > MAX_RETRIES | |
| self.hex_id = nil | |
| generate_hex_id | |
| retry | |
| end | |
| end | |
| def secure_random_safe_string(length=10) | |
| chars = [] | |
| n = SAFE_CHARS.length | |
| max = 256 - (256 % n) | |
| while chars.length < length | |
| SecureRandom.random_bytes(1).each_byte do |b| | |
| next if b >= max | |
| chars << SAFE_CHARS[b % n] | |
| break if chars.length == length | |
| end | |
| end | |
| chars.join | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment