cool id

gem for rails apps to generates string ids with a prefix, followed by a nanoid. similar to the ids you see in stripe's api. also able to lookup any record by id, similar to rails' globalid.

class User < ActiveRecord::Base
  include CoolId::Model
  cool_id prefix: "usr"
end

User.create!(name: "...").id
# => "usr_vktd1b5v84lr"

lookup any record by its id

CoolId.locate("usr_vktd1b5v84lr")
# => #<User id: "usr_vktd1b5v84lr", name: "John Doe">

and parse ids

parsed = CoolId.parse("usr_vktd1b5v84lr")
# => #<struct CoolId::Id key="vktd1b5v84lr", prefix="usr", id="usr_vktd1b5v84lr", model_class=User>

parsed.model_class
# => User

and generate ids without creating a record

# generate an id, e.g. for batch inserts or upserts
User.generate_cool_id
# => "usr_vktd1b5v84lr"

you can use cool_id with a separate field, keeping the default primary key:

class Product < ActiveRecord::Base
  include CoolId::Model
  cool_id prefix: "prd", id_field: :public_id
end

product = Product.create!(name: "Cool Product")
product.id  # => 1 (or another integer)
product.public_id  # => "prd_vktd1b5v84lr"

# You can still use CoolId.locate with the public_id
CoolId.locate("prd_vktd1b5v84lr")  # => #<Product id: 1, public_id: "prd_vktd1b5v84lr", name: "Cool Product">

this approach allows you to keep your primary key as an auto-incrementing integer while still benefiting from CoolId's functionality. it's particularly useful when you want to expose a public identifier that's separate from your internal primary key.

it takes parameters to change the alphabet or length

class Customer < ActiveRecord::Base
  include CoolId::Model
  cool_id prefix: "cus", alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZ", length: 8
end

Customer.create!(name: "...").id
# => "cus_UHNYBINU"

and these can be configured globally

CoolId.configure do |config|
  config.separator = "-"
  config.alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  config.length = 8
end

installation

add cool_id to your Gemfile:

bundle add cool_id
gem "cool_id"

adding cool_id to a single model

use string ids when creating a table

create_table :users, id: :string do |t|
  t.string :name
end

include the CoolId::Model concern in the active record model and set up a prefix

class User < ActiveRecord::Base
  include CoolId::Model
  cool_id prefix: "usr"
end

using cool_id on all models

you have drank the coolaid. setup rails to use string ids on all new generated migrations

# config/initializers/generators.rb
Rails.application.config.generators do |g|
  g.orm :active_record, primary_key_type: :string
end

then setup ApplicationRecord to include cool id and ensure it's setup in classes that inherit from it

# app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
  include CoolId::Model
  primary_abstract_class
  enforce_cool_id_for_descendants
end

graphql

if you use the graphql ruby node interface, you can implement object identification

# app/graphql/app_schema.rb
class AppSchema < GraphQL::Schema
  def self.id_from_object(object, type_definition, query_ctx)
    object.id
  end

  def self.object_from_id(id, query_ctx)
    CoolId.locate(id)
  end
end