Friendly IDs for Ruby on Rails
Dr Nic Williams
Posted on October 20, 2022
Do you have URLs like /books/1
or /secret_things/10
and wish that they were friendlier? Also, wish the IDs were sequential and guessable?
I like Stripe's URLs, such as https://dashboard.stripe.com/test/products/prod_MG5m4q7sKvGto8
. If I see the ID value prod_MG5m4q7sKvGto8
anywhere I know it belongs to a Stripe Product. cus_MG5sTiccdSlpjw
? A Stripe Customer ID. Very friendly.
And the IDs are not sequential. Friendly and random. I want this.
I'm going to show you the project I use for friendly IDs, and how I add them to my Rails scaffolding generators so they are automatically enabled for every model.
rails generate scaffold Book title description:text
And my URLs automatically pop out looking like /books/book_qYlVPJvDprRabHa0wy1xz3n9
.
A quick tweak of the generated class and they might become even nicer, /books/bk_qYlVPJvDprRabHa0wy1xz3n9
.
Yeah, you want this too.
prefixed_ids gem
The magic is provided by Chris Oliver's prefixed_ids rubygem.
The only requirement is that your models' id
column is bigint
or some other integer. I was not successful using the gem with uuid
columns. But you won't need UUID IDs because you'll have publicly friendly, random IDs, and internally sequential IDs.
bundle add prefixed_ids
Trying it out
Before we go and edit your scaffold generators, let's try it out on an existing model.
Add has_prefix_id :thing
to one of your models, and go and view it in your app.
class Book
has_prefix_id :bk
Your boring IDs now look gloriously friendly, /books/bk_x912t423
.
The gem hijacks the find
and to_param
methods. Everything just works.
Adding it to your model generator
You definitely want friendly IDs for all your future models. That is, when you run either:
rails g model Book title
rails g scaffold Book title
You want the resulting app/models/book.rb
to include the has_prefix_id :bk
link from above.
First, copy the current Rails model.rb.tt
template into your app.
If you're using Jumpstart Pro, you can skip this step.
mkdir -p lib/templates/active_record/model
curl https://raw.githubusercontent.com/rails/rails/main/activerecord/lib/rails/generators/active_record/model/templates/model.rb.tt \
-o lib/templates/active_record/model/model.rb.tt
This file will be used to generate all your future model class files.
In the newly created model.rb.tt
file, add the 3rd line:
<% module_namespacing do -%>
class <%= class_name %> < <%= parent_class_name.classify %>
has_prefix_id :<%= singular_name %>
If you were to generate a Book
model, it would look like:
class Book
has_prefix_id :book
end
You can edit :book
to :bk
. Pick an abbreviation that resonates with your URL-appreciating customers.
Show them you care.
Posted on October 20, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.