0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

supabaseのtriggerを使ってユーザーのニックネームを自動保存する方法

Posted at

はじめに

個人開発を進める際に、supabaseを用いたバックエンド開発に挑戦しました。

その際、emailとpasswordに加えてユーザーのニックネームも保存をしたかったのですが、公式サイトの実装方法が少し古いものだったり、インターネット検索もうまくヒットしなかったりと、かなり時間を費やしたので、備忘録も兼ねて実装内容をまとめようと思います。

これから実装する方の参考になれば幸いです。

前提

言語はTypeScript、フレームワークはNext.js、コードエディタはVScodeを使用しています。
ORMにはPrismaを使用して、prisma.schemaに記述したテーブル情報をsupabaseのDatabaseに反映させました。

また、この記事はSupabaseのsignIn()メソッドでユーザーの新規登録機能が実装されている前提で記載しています。未実装の方はユーザー登録実装後に参考にしてください。

私が実装したかったこと

個人開発のアプリケーションでは、当初以下のようなテーブル設計を想定していました。
※全てのカラムを書くと長くなるので、必要な箇所だけ抜粋します。

prisma.schema
model Owner {
  id            String      @id @default(uuid()) @db.Uuid
  nickname      String
  email         String
  password      String
  createdAt     DateTime    @default(now())
  updatedAt     DateTime    @updatedAt

  @@map("owners")
}

ownersテーブルに対して、ユーザー認証に必要なemailとpasswordの情報、さらにニックネームを保存する構成です。

しかし、Supabase Auth機能を使えば、簡単に認証・認可機能を実装できるため、ownersテーブルで全ての情報を管理するのではなく、「emailとpasswordはauth.usersテーブルに、nicknameはownersテーブルに保存する」出来ないかと考えました。

イメージ図

0.データベース設計.png

実装した内容

結論、supabaseのtriggerを活用することでユーザーの新規登録がされたら、同時に他のテーブルにもデータ保存ができるようになります。

今回実装する内容は、以下の4つです。

  1. signUp()メソッドでnicknameの情報を渡す
  2. auth.usersテーブルとownersテーブルを外部キーで紐づける
  3. ownersテーブルに書き込みするfunctionを作る
  4. auth.usersテーブルにレコード追加がされたら、2.のfunctionが実行されるように設定する

1. signUp()メソッドでnicknameの情報を渡す

以下のようにsignUp()でoptionを設定します。こうすることで、ユーザー登録をする際にJSON形式で追加情報を送ることができます。

今回はnicknameカラムを設定しました。

const { data, error } = await supabase.auth.signUp({
  email: 'example@email.com',
  password: 'example-password',
  options: {
    data: {
      nickname: 'John',
    },
  },
})

2. auth.usersテーブルとownersテーブルを外部キーで紐づける

まず、ownersテーブルのidカラムとauth.usersテーブルのidカラムを紐付けします。

ownersテーブルのレコードと、auth.usersテーブルのレコードで同一のuuid情報を保持することで、同一ユーザーと識別させることができます。
0.データベース設計.png

2-1.Tableを編集する

supabaseのdashboardを開き、サイドバーの「Table Editor」をクリックします。
その後変更したいテーブル名の右横にある「3点リーダー」> 「Edit Table」の順に選択してください。
1.tableEdit.png

2-2.idカラムに紐付け設定をする。

「Edit Table」をクリックすると、以下のような画面が表示されます。
真ん中あたりにあるColumnからidカラムを選択し、リンクのアイコンをクリックします。
2.カラムをリンクさせる.png

リンクをクリックすると、紐づけるテーブルとカラムを選択できます。
画像と同じように設定してください。
3.リンクさせるカラムを選択.png

2-3.オプション設定する

画面下部にある「Action if referenced row removed」で「Cascade」を選択します。
この設定をすることで、auth.usersのレコードが削除された場合は、関連するownersテーブルのデータも一緒に削除することができます。
4.removeのときにcascadeする.png

最後にSaveボタンを押して保存をしてください。

これでownersテーブルのidカラムに、auth.usersテーブルのidカラムを紐付けすることができました。

3. ownersテーブルに書き込みするfunctionを作る

続いて、ownersテーブルにnicknameカラムを書き込みするためのfunction(関数)を作ります。

こちらの動画のように、SQLで作成することもできますが、今回はdashboardから作成します。

3-1. functionを作成する

dashboardのサイドバーにある「Functions」をクリックします。
すると設定画面が表示されるので、schemaで「public」を選択した状態で「Create a new function」をクリックします。
5.create a new function.png

以下の画面でfunctionの作成をしていきます。画像のように設定してください。
6.add new function設定.png

  • Name of function
    「関数名」を記載する箇所です。任意で名前を付けられます。

  • Return type
    関数の戻り値を設定する箇所です。「trigger」を選択します。

  • Defenition
    実行する関数を記載する箇所です。以下のように記載してください。

begin
  insert into public.テーブル名 (カラム名1, カラム名2) //保存したいテーブル名とカラム名を記載する
  values (
    new.id,
    new.raw_user_meta_data->>'保存したいカラム名',
    );
  return new;
end;

newとは?

valuesの値にnew.idnew.raw_user_meta_dataの記述があります。
このnewは、新しくデータベースにデータ保存、更新、削除された際の新しいレコードを指します。

つまり、今回はauth.usersのテーブルにデータ保存がされた際に、このfunctionが実行されるためnew.idでauth.usersテーブルのidカラムのデータを取得できます。

また、new.raw_user_meta_dataは、Supabaseのauth.users テーブルで使用されるフィールドの1つです。

このフィールドには、ユーザーに関連する追加情報を保存するためのJSONオブジェクトが含まれていて、メタデータやカスタムデータが格納されています。

例)raw_user_meta_data
{
	"sub": "uuid形式のデータ",
	"email": "example@email.com",
	"nickname": "John",
	"email_verified": false,
	"phone_verified": false
}

なお、このraw_user_meta_dataには、signUp()メソッドで定義したoptionsのdataオブジェクトが含まれます。

例)signUp.tsx
const { data, error } = await supabase.auth.signUp({
  email: 'example@email.com',
  password: 'example-password',
  options: {
    data: {
      nickname: 'John',
    },
  },
})

option設定はこちらを合わせて参照してみてください。

3-2. Securityの設定をする

画面下部の「Type of Security」で「SECURITY DEFINEDER」を設定します。
この設定をすることで、この関数を作成したユーザーの権限を使って関数実行が可能になります。
7.security defenderを設定.png

4.auth.usersテーブルにレコード追加がされたら、2.のfunctionが実行されるように設定する

最後にTriggerを作成します。
Triggerとは特定のイベントと関数を紐付け、イベントの発生時に関数を発火させます。
今回は「auth.usersにレコードが追加された際に、関数実行する」という設定をしていきます。

4-1. triggerの作成をする

dashboardのサイドバーから「SQL Editor」をクリックします。
エディタが開くので、画像のように記述をします。
8.トリガーの設定.png

create trigger トリガー名 // ①任意のトリガー名
after insert on テーブル名 for each row // ②イベント対象になるテーブル。今回はauth.users
execute function 関数名 // 2.の工程で作成した関数名を記載する

上記のように記載をしたら、画面の右下の「Run」ボタンをクリックします。
クリックすることで新規トリガーが作成されます。

4-2. トリガーの作成を確認する

dashboardの「Database」から「Trigger」を選択する。
schemaで「auth」をプルダウンから選択すると、先ほど作成したtriggerが確認できます。
9.トリガーの確認.png

挙動を確認する

ここまでの設定ができたら、アプリからユーザー登録をしましょう。
以下のようにownersテーブルにもnicknameカラムが保存されていることが確認できればOKです。
10.ownerテーブルにデータ保存を確認.png

最後に

今回は主にdashboardから作成をしましたが、SQL Editorを使ってfunctionやtriggerを作る方法が公式サイトでは紹介されています。

なお、今回公式サイトの動画ではtriggerをdashboardのGUIから作っていましたが、現在その機能がないようです。(ここですごく手こずりました)

なのでSQLから作成することに慣れておく方がベターかもしれません:frowning2:

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?