Chapter 05

マイグレーションの準備

tetter / Tetta Maeda
tetter / Tetta Maeda
2023.08.26に更新

🔧 マイグレーションツールの採用

ここから先では、実装に関する具体的な説明を述べる。開発の初期段階でマイグレーションツールを導入しておくと、将来サービスが大きくなってきたときに DB の管理が非常に楽になる。初めに Diesel CLI をマイグレーションツールとして採用し、 DB を管理できるようにしておく。

なお、これ以降の Diesel に関する実装は以下を参考としている。
https://diesel.rs/guides/getting-started

🔧 インストール

PostgreSQL

今回は RDBMS として PostgreSQL を採用したいので、まずは PostgreSQL を導入する必要がある。
もしも Ubuntu であれば以下のような手順で用意することができる。
https://www.digitalocean.com/community/tutorials/how-to-install-postgresql-on-ubuntu-20-04-quickstart-ja
ただし、上記の方法は立ち上げるためにいくつかの手順が発生するため少し面倒である。

こちらも PostgreSQLのDockerイメージ が用意されているため、これを使用してコマンド一発で DB の準備を完了させてしまおう。

PC
$ docker run --name db \
             -v webapi_mvp_db_data:/var/lib/postgresql/data \
             -e POSTGRES_USER=[任意のユーザ名] \
             -e POSTGRES_PASSWORD=[任意のパスワード] \
             -e POSTGRES_DB=[任意のDB名] \
             -p 5432:5432 \
             postgres:15-bullseye

上記のコマンドは、開発に使用している PC のシェルから実行する必要があるため留意すること。

Diesel CLI

PostgreSQL を扱えるように、Rust 環境にクライアントライブラリをインストールする。

rust-dev
$ apt update
$ apt install libpq-dev

続いて、以下のコマンドで Diesel CLI をインストールする。

rust-dev
$ cargo install diesel_cli --no-default-features --features postgres

今回は PostgreSQL を使用したいので、--no-default-features --features postgres オプションを追加することで他の RDBMS (SQLite, MySQL) の特徴を取り除いてインストールする。もしもオプションをつけなかった場合、Diesel が対応している全ての RDBMS 向けのパッケージを用意しないとインストールエラーになってしまうため注意すること。

🔧 テーブルの作成

まずは PostgreSQL を立ち上げ、URL を環境変数に設定する。

rust-dev
$ export DATABASE_URL=postgres://[ユーザ名]:[パスワード]@localhost/[DB名]

続いて、以下のコマンドを実行することで Diesel CLI を使用するためのマイグレーションファイルが生成される。

rust-dev
$ diesel setup

正しく実行されていれば、以下のように migrations ディレクトリと diesel.toml ファイルが生成されている。

webapi_mvp/
 ├── Cargo.toml
 ├── diesel.toml          <-- [new!]
 ├── src/
 │    ├── main.rs
 │    └── lib.rs
 ├── tests/
 └── migrations/          <-- [new!]
      └── 00000000000000_diesel_initial_setup/
           ├── down.sql
           └── up.sql

次に、予め用意していたデータモデルに沿ってテーブルを作成する。まずは projects テーブルを作成するために以下のコマンドを実行する。

rust-dev
$ diesel migration generate create_projects

実行後、yyyy-MM-dd-hhmmss_create_projects ディレクトリが生成されるので、up.sql を以下のように書き換える。

migrations/yyyy-MM-dd-hhmmss_create_projects/up.sql
CREATE TABLE projects(
    id BIGSERIAL PRIMARY KEY,
    --------
    name VARCHAR NOT NULL,
    url_name VARCHAR NOT NULL UNIQUE
);

記載方法は SQL 文に従う。同様の手順で technologies テーブル、adopts テーブルを作成するためのディレクトリを用意し、以下のように SQL 文を記載する。

migrations/yyyy-MM-dd-hhmmss_create_technologies/up.sql
CREATE TABLE technologies(
    id BIGSERIAL PRIMARY KEY,
    --------
    name VARCHAR NOT NULL,
    url_name VARCHAR NOT NULL UNIQUE,
    image_url VARCHAR NOT NULL
);
migrations/yyyy-MM-dd-hhmmss_create_adopts/up.sql
CREATE TABLE adopts(
    id BIGSERIAL PRIMARY KEY,
    --------
    projects_id BIGINT NOT NULL,
    FOREIGN KEY (projects_id) REFERENCES projects(id),
    technologies_id BIGINT NOT NULL,
    FOREIGN KEY (technologies_id) REFERENCES technologies(id),
    --------
    created_at TIMESTAMP WITH TIME ZONE NOT NULL
);

🔧 マイグレーションの実行

マイグレーションファイルが用意できたら、以下のコマンドを実行することで DB へ反映させることができる。

rust-dev
$ diesel migration run

また、上記のコマンドを実行することで、DB のスキーマを実装した src/schema.rs ファイルが自動的に生成される。
Diesel CLI の設定が完了すると、以下のようなディレクトリ構成となっているはずである。


webapi_mvp/
 ├── Cargo.toml
 ├── diesel.toml
 ├── src/
 │    ├── main.rs
 │    ├── lib.rs
 │    └── schema.rs                                 <-- [new!]
 ├── tests/
 └── migrations/
      ├── 00000000000000_diesel_initial_setup/
      │    ├── down.sql
      │    └── up.sql
      ├── yyyy-MM-dd-hhmmss_create_projects/        <-- [new!]
      │    ├── down.sql
      │    └── up.sql
      ├── yyyy-MM-dd-hhmmss_create_technologies/    <-- [new!]
      │    ├── down.sql
      │    └── up.sql
      └── yyyy-MM-dd-hhmmss_create_adopts/          <-- [new!]
           ├── down.sql
           └── up.sql

🔧 ロールバックの実行

ロールバックを実行するためには、予め down.sql にロールバック用の SQL 文を用意しておく必要がある。例えば、projects テーブルを消去するためには以下のように記載しておく。

migrations/yyyy-MM-dd-hhmmss_create_projects/down.sql
DROP TABLE projects;

もしも DB を以前の状態に戻したい場合、以下のコマンドを実行すると、down.sql の内容に従って1つ前の状態にロールバックされる。

rust-dev
$ diesel migration revert

あるいは、最新のマイグレーションをもう一度やり直したい場合は、以下のコマンドを実行することで最も新しい down.sql -> up.sql の順に実行される。

rust-dev
$ diesel migration redo