In some situations it's ideal to be able to hide the ID number in a database table. Here's how to do it using Crystal Amber and the Granite ORM.
Create your model
amber g model WebLink url:string
Edit the migration file to use either a VARCHAR or UUID if it supports it (Hint: Postgres does!). To use a hex string instead, stick with VARCHAR.
-- +micrate Up
CREATE TABLE web_links (
id UUID PRIMARY KEY,
url VARCHAR,
created_at TIMESTAMP,
updated_at TIMESTAMP
);
-- +micrate Down
DROP TABLE IF EXISTS web_links;
Edit the model file to include the UUID library, set the Primary Key as a string and turn off auto increment. Then add the before_create macro to assign a new UUID on creation.
require "uuid"
class WebLink < Granite::Base
adapter pg
table_name web_links
# id : Int64 primary key is created for you
primary id : String, auto: false
field url : String
timestamps
before_create :assign_id
def assign_id
@id = UUID.random.to_s
end
end
Alternatively, use UUID.random.hexstring.to_s for an alternate style (e.g. 2d10e1a2fa89425197d62f94c6cf07dc). The UUID database data type will convert this automatically so make sure to set the data type to VARCHAR.
To use shorter IDs chop the hexstring down by using the range syntax [0..6], replacing 6 with the desired length, and then check for duplicates before creating the table row.
def assign_id
potential_id = UUID.random.hexstring.to_s[0..6]
while WebLink.find(potential_id)
potential_id = UUID.random.hexstring.to_s[0..6]
end
@id = potential_id
end
That's it! Make sure to run crystal db migrate before running the application.