🌽

RailsでモデルのIDをStripeのAPIのようにする Prefixed IDs gem

公開日
5か月前
2024-01-30
更新履歴

gem

GitHub - excid3/prefixed_ids: Friendly Prefixed IDs for your Ruby on Rails models
Friendly Prefixed IDs for your Ruby on Rails models - excid3/prefixed_ids
github.com favicon
github.com
GitHub - excid3/prefixed_ids: Friendly Prefixed IDs for your Ruby on Rails models

概要

StripeのAPIでは各リソースのIDが cus_12345abcd のように プレフィックス+ランダムな文字列 になっています。RailsのモデルのIDをこのような形式で扱うための便利なgemです。

DBのAUTO_INCREMENTな値をIDとしてそのまま使いたくない。でも、UUIDみたいなカラムを追加するのも。。。みたいなときにありがたいですね。GraphQLの場合は、それぞれのリソース毎にグローバルでユニークなIDをつけた方が良いので、そんな時にも使えます。

使い方

  1. Gemfileに以下を追加して bundle install を実行します。

    Gemfile
    gem 'prefixed_ids'
    
  2. Prefixed IDsのランダムな文字列を生成するためのsaltを設定します。以下のようにすることで、環境変数で設定できるようになります。bundle exec rails secretなどで生成した文字列を設定しておきましょう。

    config/initializers/prefixed_ids.rb
    PrefixedIds.salt = ENV.fetch('PREFIXED_IDS_SALT')
    
  3. Prefixed IDsを有効にしたいモデルに以下のように has_prefix_id :user を追加します。:user の部分はプレフィックスになるので u_abc123 のようにしたい場合は :u にしましょう。

    app/models/user.rb
    class User < ApplicationRecord
        has_prefix_id :user
    end
    
  4. 以上で簡単な設定は終わりです。以下のようにしてレコードを取得できるようになります。

    レコードを取得する
    user = User.find(1)
    puts user.id # 1
    puts user.prefix_id # user_mX6g41alvDZ9Zu6Ro7AOejE3
    
    user2 = User.find('user_mX6g41alvDZ9Zu6Ro7AOejE3')
    puts user == user2 # true
    
    user3 = PrefixedIds.find('user_mX6g41alvDZ9Zu6Ro7AOejE3')
    puts user == user3 # true
    

高度な設定: Model.findメソッドで指定できるIDをどちらか一方にできる

デフォルトでは find で通常のIDとPrefixed IDのどちらを指定してもレコードが取得できますが、どちらか一方に制限することができます。

通常のIDのみにしたい場合

Prefixed
class User < ApplicationRecord
  has_prefix_id :user, override_find: false, override_param: false
end

# OK
User.find(1)

# Error
User.find('user_mX6g41alvDZ9Zu6Ro7AOejE3')
# Couldn't find User with 'id'=user_mX6g41alvDZ9Zu6Ro7AOejE3

Prefixed IDのみにしたい場合

Prefixed
class User < ApplicationRecord
  has_prefix_id :user, override_find: true, override_param: true, fallback: false
end

# OK
User.find('user_mX6g41alvDZ9Zu6Ro7AOejE3')

# Error
User.find(1)
# 1 is not a valid prefix_id