Using binary ids / UUIDs for database primary keys in Rails.

It's generally a good idea to use binary ids / UUIds for the primary keys in your database.

Here's how to easily do it in Rails 7, using Postgres!

Configure your generators to use UUID for keys.

Create a file in config/initializers/generators.rb

Rails.application.config.generators do |g|
  g.orm :active_record, primary_key_type: :uuid
end

Now when you generate models it'll automatically use uuids for the primary keys. This even works automatically for things like action_text.

Here's what the action_text generator will create for you:

# This migration comes from action_text (originally 20180528164100)
class CreateActionTextTables < ActiveRecord::Migration[6.0]
  def change
    # Use Active Record's configured type for primary and foreign keys
    primary_key_type, foreign_key_type = primary_and_foreign_key_types

    create_table :action_text_rich_texts, id: primary_key_type do |t|
      t.string     :name, null: false
      t.text       :body, size: :long
      t.references :record, null: false, polymorphic: true, index: false, type: foreign_key_type

      t.timestamps

      t.index [ :record_type, :record_id, :name ], name: "index_action_text_rich_texts_uniqueness", unique: true
    end
  end

  private
    def primary_and_foreign_key_types
      config = Rails.configuration.generators
      setting = config.options[config.orm][:primary_key_type]
      primary_key_type = setting || :primary_key
      foreign_key_type = setting || :bigint
      [primary_key_type, foreign_key_type]
    end
end

Notice the id type! Pretty nifty.

Make sure your foreign keys use UUID!

When you start creating more tables, make sure the type is correct.

class CreateQuotes < ActiveRecord::Migration[7.1]
  def change
    create_table :quotes, id: :uuid do |t|
      t.text :favorite_quote
      t.uuid :user_id

      t.timestamps
    end
  end
end

t.uuid! Don't forget!

And it's that easy.