RailsでPostgreSQLを使った開発でプライマリーキーにuuidを設定する道のり

## この記事で書くこと :pencil: 
毎回躓く度に既視感があるので、表題の件に対する設定方法を自分用にきちんとまとめておく。
ちなみに動作環境は以下

```bash

Rails: 6.0.3.2
Ruby: ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux]
PostgreSQL: psql (PostgreSQL) 12.2 (Debian 12.2-2.pgdg100+1)
```

## 結論 :dolphin: 
1. まず、postgresでuuidを生成するための関数をもつモジュールが何かを確認する。( `pgcrypto` )
2. そのモジュールを使えるようにするマイグレーションを作成する
3. マイグレーション実行

## 躓くところ :stop_button: 

例えば以下のようなマイグレーションファイルを作成したとする。

```rb:db/migrate/xxxxxxx_create_users.rb

class CreateUsers < ActiveRecord::Migration[6.0]
  def change
  ¦ create_table :users, id: :uuid do |t|
  ¦ ¦ t.string :nickname
  ¦ ¦ t.string :icon_image

  ¦ ¦ t.timestamps
  ¦ end
  end
end
```

意気揚々とmigrationしようとする。

```bash

$ rake db:migrate
```

エラーが起きる

```
Caused by:
PG::UndefinedFunction: ERROR:  function gen_random_uuid() does not exist
LINE 1: CREATE TABLE "users" ("id" uuid DEFAULT gen_random_uuid() NO...
```

この `gen_random_uuid()` どこで設定されているのかというと、
[PostgreSQL 12.0文書](https://www.postgresql.jp/document/12/html/pgcrypto.html#id-1.11.7.34.9) を見ると、pgcryptoモジュールで定義されているのがわかる。


[Railsガイド | Active Record と PostgreSQL#2.UUID主キー](https://railsguides.jp/active_record_postgresql.html#uuid%E4%B8%BB%E3%82%AD%E3%83%BC) を確認すると、migrationで、モジュールを拡張する必要があるらしいことがわかる。

以下のmigrationを作成。

```rb:db/migrate/xxxxxxx_enable_extension_for_uuid.rb
class EnableExtensionForUuid < ActiveRecord::Migration[6.0]
  def change
  ¦ enable_extension 'pgcrypto' unless extension_enabled?('pgcrypto')
  end
end
```


migrationしようとする。

```bash

$ rake db:migrate
```

エラーが出る。

```bash

Caused by:
PG::InsufficientPrivilege: ERROR:  permission denied to create extension "pgcrypto"
HINT:  Must be superuser to create this extension.
```

superuserじゃないと、できません。と言われる。
確かにアプリケーション用に、新しくuserを作成していたのでsuperuserではない。

superuserにするしか本当に出来ないのかを確かめるために、アプリケーション用のuserでpostgresにログインし、コマンドで処理できないか試す。

```bash

=> CREATE EXTENSION IF NOT EXISTS "pgcrypto";
ERROR:  permission denied to create extension "pgcrypto"
HINT:  Must be superuser to create this extension.
```

ダメだった。 :disappointed: 
ので、大人しく `ALTER ROLE` する。

```bash

=# \du
                                     List of roles
   Role name   |                         Attributes                         | Member of

---------------+------------------------------------------------------------+----------
-
 app_user_role | Create DB                                                  | {}
 postgres      | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

postgres=# ALTER ROLE app_user_role SUPERUSER;
ALTER ROLE
# \du
                                     List of roles
   Role name   |                         Attributes                         | Member of

---------------+------------------------------------------------------------+----------
-
 app_user_role | Superuser, Create DB                                       | {}
 postgres      | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
```

migrationを実行する

```bash

$ rake db:migrate

== xxxxxxxxxxxx EnableExtensionForUuid: migrating ===========================
-- extension_enabled?("pgcrypto")
   -> 0.0142s
-- enable_extension("pgcrypto")
   -> 0.1541s
== xxxxxxxxxxxx EnableExtensionForUuid: migrated (0.1710s) ==================

== yyddddddddddd CreateUsers: migrating ======================================
-- create_table(:users, {:id=>:uuid})
   -> 0.0839s
== yyddddddddddd CreateUsers: migrated (0.0840s) =============================

```

:tada: :tada:



## 関連情報のようなもの :cat2: 

uuidを常にprimary keyに設定したいときは以下の内容でファイルを用意する。

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