🤖
UUID主キーをActiveRecordで使う(PostgreSQL 13+)
Modelでの設定は不要で、カラムがPostgreSQLのUUID型で作成されていれば扱えます。
- migrationの
create_table
のid:
オプションに:uuid
を渡す(create_table のドキュメント) - 外部キーとして参照する場合
t.references
のオプションに:uuid
を渡す(references のドキュメント)
サンプルコード
db/migrate/20230115084803_create_backets.rb
class CreateBackets < ActiveRecord::Migration[7.0]
def change
create_table :backets, id: :uuid do |t|
t.timestamps
end
end
end
db/migrate/20230115090623_create_items.rb
class CreateItems < ActiveRecord::Migration[7.0]
def change
create_table :items, id: :uuid do |t|
t.string :name, null: false
t.integer :price, null: false
t.timestamps
end
end
end
db/migrate/20230115090735_create_backet_items.rb
class CreateBacketItems < ActiveRecord::Migration[7.0]
def change
create_table :backet_items, id: :uuid do |t|
t.references :backet, null: false, foreign_key: true, type: :uuid
t.references :item, null: false, foreign_key: true, type: :uuid
t.index %i[backet_id item_id], unique: true
t.integer :quantity, null: false
t.timestamps
end
end
end
生成されるスキーマ
db/schema.rb
ActiveRecord::Schema[7.0].define(version: 2023_01_15_090735) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "backet_items", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.uuid "backet_id", null: false
t.uuid "item_id", null: false
t.integer "quantity", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["backet_id", "item_id"], name: "index_backet_items_on_backet_id_and_item_id", unique: true
t.index ["backet_id"], name: "index_backet_items_on_backet_id"
t.index ["item_id"], name: "index_backet_items_on_item_id"
end
create_table "backets", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "items", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.string "name", null: false
t.integer "price", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_foreign_key "backet_items", "backets"
add_foreign_key "backet_items", "items"
end
default: "gen_random_uuid()" は不要
生成されるスキーマを見てわかるように、UUID生成のための gen_random_uuid()
は自動で設定されるため、migrationにおいて default: "gen_random_uuid()"
は不要です。
enable_extension 'pgcrypto' は不要
PostgreSQL 13以上では gen_random_uuid()
に pgcrypto
拡張は不要です。
PostgreSQL 12以下の場合は、 create_table id: :uuid
の前に拡張の有効化が必要です。
enable_extension 'pgcrypto' unless extension_enabled?('pgcrypto')
generatorによって作成されるmigrationの主キーのデフォルト
次のように設定しておくと作成されるmigrationの主キー型と外部キー型のデフォルトが :uuid
になります。
config/application.rb
module MyApp
class Application < Rails::Application
# 省略
config.generators do |g|
g.orm :active_record, primary_key_type: :uuid
end
end
end
参考
Discussion