Railsアプリへのuuidの適用方法
Railsアプリへのuuid適用方法などは、弊社の技術記事[Rails] モデルのIDにUUIDを使って玄人感を出すで既に書かれているので省略します。
今回は既存テーブルのidを変更するため、どのようにマイグレーションするか?がメインです。
uuidをrailsアプリに適用するコードだけ記します。
postgresqlのuuid拡張機能を有効化
rails g migration enable_extension_for_uuid
class EnableExtensionForUuid < ActiveRecord::Migration[6.0] def change enable_extension 'pgcrypto' unless extension_enabled?('pgcrypto') end end
initializers内でprimary keyのデフォルト値をuuid化
Rails.application.config.generators do |g| g.orm :active_record, primary_key_type: :uuid end
Railsアプリへの詳しいuuid適用方法は下記を参照してください! [Rails] モデルのIDにUUIDを使って玄人感を出す
バージョン
- Ruby 2.7.0
- Rails 6.0.3.4
- PostgreSQL 13.0
スキーマ
下記構成で記述します
テーブル名
- アソシエーション
- アソシエーション
users
- has_many event_participants
events
- has_many event_participants
event_participants
- belongs_to users
- belongs_to events
users
id | name |
---|---|
1 | hoge |
2 | huga |
events
id | name |
---|---|
1 | hoge |
2 | huga |
event_participants
id | event_id | user_id |
---|---|---|
1 | 1 | 1 |
2 | 2 | 1 |
3 | 2 | 2 |
上の構成ですべてですが、ざっくり日本語で書くと、ユーザーがイベントに参加できて、イベントの参加者を多対多の中間テーブルで管理する。みたいな感じです。
マイグレーション
まずusersテーブルからマイグレーションしていきます。
class ChangeUserIdTypeToUuid < ActiveRecord::Migration[6.0] def up # usersテーブルにuuid追加 add_column :users, :uuid, :uuid, null: false, default: 'gen_random_uuid()' # 関連テーブルにuuid追加 add_column :event_participants, :user_uuid, :uuid # 関連テーブルのuuidを更新(これでusersのuuidとevent_participantsのuser_uuidが紐づく) execute <<~SQL UPDATE event_participants SET user_uuid = users.uuid FROM users WHERE event_participants.user_id = users.id; SQL # usersの元々のprimary keyであるidを消す # 外部キーとして参照されていると消せないので、関連テーブルからの参照を切る remove_foreign_key :event_participants, :users remove_reference :event_participants, :user, index: true # usersのidを消して、追加したuuidのカラム名をidに変更 change_table :users do |t| t.remove :id t.rename :uuid, :id end # usersのuuid化したidをprimary keyとして設定 execute 'ALTER TABLE users ADD PRIMARY KEY (id);' # 関連テーブルに追加したuuidを元々あった名前に変更(元々あったuser_idはusersテーブルのidを消した時に消えてるはずなので競合しない) rename_column :event_participants, :user_uuid, :user_id # 関連テーブルのuuid化したuser_idを外部キーとして設定 add_foreign_key :event_participants, :users add_index :event_participants, :user_id change_column_null :event_participants, :user_id, false end def down # idに戻すことは無いと思うのでrollback不可を明示的にする raise ActiveRecord::IrreversibleMigration end end
これでusersのidと関連テーブルであるevent_participansのuser_idがuuidに変更できたと思います。
eventsテーブルも同じ要領でできますね。
最後にevent_participantsのidを変更していきます。
class ChangeEventParticipantsIdTypeToUuid < ActiveRecord::Migration[6.0] def up # event_partivipantsテーブルにuuid追加 add_column :event_participants, :uuid, :uuid, null: false, default: 'gen_random_uuid()' # event_participantsのidを消して、追加したuuidのカラム名をidに変更 change_table :event_participants do |t| t.remove :id t.rename :uuid, :id end # event_participantsのuuid化したidをprimary keyとして設定 execute 'ALTER TABLE event_participants ADD PRIMARY KEY (id);' end def down raise ActiveRecord::IrreversibleMigration end end
外部キーとして参照されてないidをuuidに変更するのはシンプルですね!
まとめ
やはり作成済みのテーブルのidを変更するにはひと手間かかりますね。 常にユーザーがアクセスしている本番環境で途中から変更するのは中々現実的ではないとは思いますが、 ローンチ前かつデータがちょっと入ってて消したくない(消えてもそんな問題じゃない)。みたいな時には役立つかなと思いました。
やっぱidよりuuidの方がかっちょいい!