こんにちは!kossyです!
今回はRailsでPostgreSQLを使う際にgen_random_uuid関数を有効化する方法について、
備忘録としてブログに残してみたいと思います。
環境
Ruby 2.6.9
Rails 6.0.4
PostgreSQL 13系
マイグレーションファイルの作成
gen_random_uuid関数を有効化するために、マイグレーションファイルを作成し、以下のように変更します。
class EnableUuidExtension < ActiveRecord::Migration[6.0] def change enable_extension 'pgcrypto' end end
その後migrateを実行。
$ rails db:migrate == 20211216142135 EnableUuidExtension: migrating ============================== -- enable_extension("pgcrypto") -> 0.0554s == 20211216142135 EnableUuidExtension: migrated (0.0556s) =====================
これでマイグレーションファイル内でgen_random_uuid関数が使えるようになります。
テーブルの作成
試しにテーブルを作成して、uuid型のデフォルト値にgen_random_uuid関数を指定してみます。
class CreateTenants < ActiveRecord::Migration[6.0] def change create_table :tenants do |t| t.string :name, null: false t.uuid :uuid, null: false, default: 'gen_random_uuid()' t.timestamps end end end
migrateコマンドを実行した後、schema.rbを確認してみます。
create_table "tenants", force: :cascade do |t| t.string "name", null: false t.uuid "uuid", default: -> { "gen_random_uuid()" }, null: false t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false end
default値にgen_random_uuid関数が指定できているようです。
動作確認
試しにtenantsテーブルにレコードを新規作成してみます。
$ Tenant.create!(name: 'その辺にいるWebエンジニア株式会社') (0.5ms) BEGIN Tenant Exists? (4.5ms) SELECT 1 AS one FROM "tenants" WHERE "tenants"."id" = $1 LIMIT $2 [["id", nil], ["LIMIT", 1]] Tenant Create (3.7ms) INSERT INTO "tenants" ("name", "uuid", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["name", "その辺にいるWebエンジニア株式会社"], ["uuid", "b5188d11-d9a3-423b-be17-dae29800977e"], ["created_at", "2021-12-16 13:16:51.489288"], ["updated_at", "2021-12-16 13:16:51.489288"]] (3.8ms) COMMIT
uuidにデフォルト値が挿入されていることがわかります。
念のためきちんとランダムな値になっているかどうかも確認してみます。
$ Tenant.create!(name: 'ランダム株式会社') (0.8ms) BEGIN Tenant Exists? (7.4ms) SELECT 1 AS one FROM "tenants" WHERE "tenants"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]] Tenant Exists? (4.4ms) SELECT 1 AS one FROM "tenants" WHERE "tenants"."id" = $1 LIMIT $2 [["id", nil], ["LIMIT", 1]] Tenant Create (0.9ms) INSERT INTO "tenants" ("name", "uuid", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["name", "ランダム株式会社"], ["uuid", "a46244c4-8a3a-4b48-8236-1e76b475b4da"], ["created_at", "2021-12-16 13:19:26.898640"], ["updated_at", "2021-12-16 13:19:26.898640"]] (1.4ms) COMMIT
先ほどと異なるuuidが生成されているので、ランダムな値になっているようです。
uuid_generate_v4じゃダメなの?
uuid_generate_v4という関数もあるんですが、PostgreSQLのドキュメントを見たところ、
注意: ランダムに生成された(バージョン4)UUIDのみが必要な場合には、代わりにpgcryptoモジュールのgen_random_uuid()を利用すること検討してください。
という記述があったため、ランダムに生成された(バージョン4)UUIDのみが必要な場合にはpgcryptoモジュールを有効化するのがデファクトスタンダートのようです。
まとめ
Railsだとfriendly_id Gemを用いる際にuuidを設定することがあると思いますが、その場合にはpgcryptoモジュールを有効化するのを忘れないようにしましょう。(私は10分ハマりました)