Friendly IDs for Ruby on Rails

friendly-ids-for-ruby-on-rails

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.

Total
1
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post
performance-comparison:-reduct-storage-vs.-minio

Performance comparison: Reduct Storage vs. Minio

Next Post
all-the-ways-to-render-an-actiontext-attachment

All the ways to render an ActionText Attachment

Related Posts