CloudFlareにデプロイするためのRemixプロジェクトにテーブルを追加してみる

## 概要

前回下記で作成したRemixのプロジェクトにはusersテーブルが一つだけある。

https://qiita.com/miriwo/items/04ae58a0705cc54e198c

CURDを学びたいからTODOリストのアプリでも作ってみようと思っている。

今回はやることを管理するtasksテーブルと、タスクのカテゴリを管理するtask_category_mastersテーブルを追加する

## 前提

- CloudFlare上のD1データベース名は「todo-cloudflare-d1」とする。よってwrangler.tomlでdatabase_nameが`todo-cloudflare-d1`と指定されているものとする。

## 追加するテーブル

余談だが、usersテーブルを作ったものの、今回は認証などをいれるつもりがないのでtasksテーブルにuser_idカラムは今は持たなかった。

### tasksテーブル

| カラム名 | データ型 | Not null | 備考 |
| --- | --- | --- | --- |
| id | int | YES | オートインクリメント 主キー |
| name | text | YES | タスク名 |
| memo | text | NO | 詳細 |
| is_complete | int | YES | 完了可否 0：未完了/1：完了 |
| task_category_master_id | int | YES | task_category_mastersテーブルのid |
| created_at | datetime | YES | レコード作成日時 |
| updated_at | datetime | YES | レコード更新日時 |
| deleted_at | datetime | NO | レコード削除日時 |

### task_category_mastersテーブル

| カラム名 | データ型 | Not null | 備考 |
| --- | --- | --- | --- |
| id | int | YES | オートインクリメント 主キー |
| name | text | YES | タスクカテゴリ名 |
| created_at | datetime | YES | レコード作成日時 |
| updated_at | datetime | YES | レコード更新日時 |
| deleted_at | datetime | NO | レコード削除日時 |

## 作業

下記の作業を実施して各テーブルの追加を行う。

### task_category_mastersテーブル追加

1. `prisma/schema.prisma`のファイルに下記の内容を追記

    ```prisma/shcema.prisma
    // usersテーブルのスキーマもすでに記載されている
    
    model task_category_masters {
      id    Int     @id @default(autoincrement())
      name  String
      tasks tasks[]
    }
    ```

1. 下記を実行してPrismaによりマイグレーションSQL句が記載されるファイルを作成（migrationsディレクトリ直下に000X_create_task_category_masters_table.sqlが作成されるはず）

    ```sh
    npx wrangler d1 migrations create todo-cloudflare-d1 create_task_category_masters_table
    ```

1. 下記を実行して先に作成したファイルにマイグレーションSQL句を自動記載するコマンドを実行（000Xの部分は先のコマンドで作成されたファイル名に置き換えてコマンドを実行する）

    ```sh
    npx prisma migrate diff --from-empty --to-schema-datamodel ./prisma/schema.prisma --script --output migrations/000X_create_task_category_masters_table.sql
    ```

1. `migrations/000X_create_task_category_masters_table.sql`を確認すると下記のようにusersテーブル系の情報も格納されてしまっている。`migrations/000X_create_task_category_masters_table.sql`のusersテーブル系の情報・tasksテーブル系の情報は手動で削除

    - 削除前

        ```migrations/000X_create_task_category_masters_table.sql
        -- CreateTable
        CREATE TABLE "users" (
            "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
            "email" TEXT NOT NULL,
            "name" TEXT NOT NULL
        );
        
        -- CreateTable
        CREATE TABLE "task_category_masters" (
            "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
            "name" TEXT NOT NULL
        );
        
        -- CreateIndex
        CREATE UNIQUE INDEX "users_email_key" ON "users"("email");
        ```

    - 手動削除後

        ```migrations/000X_create_task_category_masters_table.sql
        -- CreateTable
        CREATE TABLE "task_category_masters" (
            "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
            "name" TEXT NOT NULL
        );

        ```

1. 下記を実行してローカルのD1のDBに対してマイグレーションを行う。

    ```sh
    npx wrangler d1 migrations apply todo-cloudflare-d1 --local
    ```

### tasksテーブル追加

1. `prisma/schema.prisma`のファイルに下記の内容を追記

    ```prisma/shcema.prisma
    // usersテーブルのスキーマもすでに記載されている
    
    model task_category_masters {
      id    Int     @id @default(autoincrement())
      name  String
      tasks tasks[] // 追記
    }
    
    model tasks {
      id                      Int      @id @default(autoincrement())
      name                    String
      memo                    String?
      is_complete             Int
      task_category_master_id Int
      created_at              DateTime @default(now())
      updated_at              DateTime @updatedAt
      deleted_at              DateTime?
    
      // リレーション
      task_category_master    task_category_masters @relation(fields: [task_category_master_id], references: [id])
    }
    ```

1. 下記を実行してPrismaによりマイグレーションSQL句が記載されるファイルを作成（migrationsディレクトリ直下に000X_create_tasks_table.sqlが作成されるはず）

    ```sh
    npx wrangler d1 migrations create todo-cloudflare-d1 create_tasks_table
    ```

1. 下記を実行して先に作成したファイルにマイグレーションSQL句を自動記載するコマンドを実行（000Xの部分は先のコマンドで作成されたファイル名に置き換えてコマンドを実行する）

    ```sh
    npx prisma migrate diff --from-empty --to-schema-datamodel ./prisma/schema.prisma --script --output migrations/000X_create_tasks_table.sql
    ```

1. `migrations/000X_create_tasks_table.sql`を確認すると下記のようにusersテーブル系の情報も格納されてしまっている。`migrations/000X_create_tasks_table.sql`のusersテーブル系の情報は手動で削除

    - 削除前

        ```migrations/000X_create_tasks_table.sql
        -- CreateTable
        CREATE TABLE "users" (
            "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
            "email" TEXT NOT NULL,
            "name" TEXT NOT NULL
        );
        
        -- CreateTable
        CREATE TABLE "task_category_masters" (
            "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
            "name" TEXT NOT NULL
        );
        
        -- CreateTable
        CREATE TABLE "tasks" (
            "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
            "name" TEXT NOT NULL,
            "memo" TEXT,
            "is_complete" INTEGER NOT NULL,
            "task_category_master_id" INTEGER NOT NULL,
            "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
            "updated_at" DATETIME NOT NULL,
            "deleted_at" DATETIME,
            CONSTRAINT "tasks_task_category_master_id_fkey" FOREIGN KEY ("task_category_master_id") REFERENCES "task_category_masters" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
        );
        
        -- CreateIndex
        CREATE UNIQUE INDEX "users_email_key" ON "users"("email");

        ```

    - 手動削除後

        ```migrations/000X_create_tasks_table.sql
        -- CreateTable
        CREATE TABLE "tasks" (
            "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
            "name" TEXT NOT NULL,
            "memo" TEXT,
            "is_complete" INTEGER NOT NULL,
            "task_category_master_id" INTEGER NOT NULL,
            "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
            "updated_at" DATETIME NOT NULL,
            "deleted_at" DATETIME,
            CONSTRAINT "tasks_task_category_master_id_fkey" FOREIGN KEY ("task_category_master_id") REFERENCES "task_category_masters" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
        );

        ```

1. 下記を実行してPrismaのクライアントを再度生成しておく。

    ```sh
    npx prisma generate
    ```

1. 下記を実行してローカルのD1のDBに対してマイグレーションを行う。

    ```sh
    npx wrangler d1 migrations apply todo-cloudflare-d1 --local
    ```

1. table plusなどでローカルのD1（`.wrangler/stage/v3/d1/miniflare-D1DatabaseObject`直下の.sqliteファイルを指定）を確認して、下記のようにテーブルができていればひとまず完了

    ![CleanShot 2024-06-14 at 01.13.27@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/1dc308fe-c3c6-5c01-1d6f-8b9a40b552cf.png)    

## 自分用メモ

schema.prismaのファイルに変更を加えたら`npx prisma generate`を実行してクライアントを再作成しておく。

## 参考文献

### Prismaでモデル定義

https://www.prisma.io/docs/orm/prisma-schema/data-model/models

### Prismaでvarcharを指定

https://www.prisma.io/docs/orm/prisma-schema/data-model/models#native-types-mapping

### リレーションの指定

https://www.prisma.io/docs/orm/prisma-schema/data-model/relations