おなじみのとおり、Ruby on Railsの各モデルのidは自動生成される連番数値(INTEGER)がデフォルトです。ただ、Rails 4以降では、設定しだいでUUIDも使えます。
ある程度以上の規模のサービスを考えるとAUTO INCREMENTでは何かの拍子にモデル間の不整合が起きる可能性があるため、「事実上衝突しない」というメリットがあるUUIDの利用を検証してみました。
結論からいうと、ridgepoleとPostgreSQLを用いた構成では、以下の手順でPRIMARY KEYにuuidを利用できます。
- migrationでPostgreSQLのuuid機能をオンに設定する
- ridgepoleのidオプションに:uuidを指定して、apply
migrationでPostgreSQLのuuid機能をオンにする
まずmigrationについては、 Rails 5.1 + Using a UUID as a primary key in ActiveRecord with PostgreSQLに記載されているmigrationを作成・実行します。
(PostgreSQL v9.3以前では、 Use UUIDs in Rails 4 with PostgreSQLの手順でないと動作しないかもしれません)
$ rails g migration enable_pgcrypto_extension
db/migrateに生成されたファイルに1行追加。
class EnablePgcryptoExtension < ActiveRecord::Migration[5.1]
def change
enable_extension 'pgcrypto'
end
end
$ rails db:migrate
を実行
== 20150705164619 EnablePgcryptoExtension: migrating ==========================
-- enable_extension("pgcrypto")
-> 0.0629s== 20150705164619 EnableUuidOsspExtension: migrated (0.0095s) =================
ridgepoleのスキーマ定義でidをuuidに
ridgepoleのSchemafileで、create_tableのオプションにid: :uuid
を指定することで、idの設定が変わります。
create_table "users", id: :uuid do |t|
end
$ ridgepole -c config/database.yml -f config/Schemafile -a
を実行。
Apply `config/Schemafile`
-- create_table("users", {:id=>:uuid})
-> 0.0161s
pgcryptoを有効にしていないときのエラー
ridgepoleを使っているのにmigrationも実行するというのは中途半端な印象もありますが、ridgepoleではpgcryptoをenableできず、以下のようなエラーになります。
$ ridgepole -c config/database.yml -f config/Schemafile -a
Apply `config/Schemafile`
-- create_table("users", {:id=>:uuid})
[ERROR] PG::UndefinedFunction: ERROR: function gen_random_uuid() does not exist
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
: CREATE TABLE "users" ("id" uuid DEFAULT gen_random_uuid() NOT NULL PRIMARY KEY, "name" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
* 1: create_table("users", {:id=>:uuid}) do |t|
2: t.string("name", {})
ほかの手段としては、以下のようにpsqlコマンドからPostgreSQLを直接操作して設定をオンにすることもできます。
postgres=# c SOME_DB_NAME;
SOME_DB_NAME=# create extension "pgcrypto";
ただし、環境設定をConfigファイル化しておかないと、リカバリの際などに作業漏れの危険もあるため、とくにridgepoleの動作に支障がなければmigrationの利用は現実的な妥協点として成立するように思います。
Chuma Takahiro