Expressで簡易APIサーバー作成_1　Sequelizeでマイグレーションしてみる

## 概要
オリジナルアプリのフロントをReactで作成していて、APIサーバーをExpressで作成してみることにしました。バックでのJavaScriptの使われ方を知りたいと思っていたことがきっかけです。

公式によるとExpressとは、次の通りです。
>Express は、Web アプリケーションとモバイル・アプリケーション向けの一連の堅固な機能を提供する最小限で柔軟な Node.js Web アプリケーション・フレームワークです。

ExpressでもRailsのActiveRecordのようにORMでDBを扱いたいと思っていたところ、Sequelizeというパッケージがあるようです。
使い方を調べてみました。

## 目的
ExpressのスケルトンからSequelizeを使ってCRUDの雛形をささっと作れるようなるために、手順をアウトプットすることが目的です。
今後、何回かに分けてアウトプットしていこうと思います。

今回の目標は次の通りです。

* Expressアプリーケーションのスケルトンを作成する。
* ユーザーを表すシンプルなモデルを作成する。
* マイグレーションを実行してユーザーテーブルを作成する。

## References
* [Express公式ドキュメント](https://expressjs.com/)
* [Express公式ドキュメント(和訳)](https://expressjs.com/ja/)
* [Sequelize公式ドキュメント](https://sequelize.org/master/index.html)
* [Sequelize CLIのRead Me](https://github.com/sequelize/cli)
* [便利！Node.jsにDBマイグレーション、Seed、モデルを用意する「Sequelize」](https://blog.capilano-fw.com/?p=5546) 

## 検証環境
* MacOS Catalina 10.15.7
* Node.js 14.5.0
* mysql 5.6.47

Node.jsと使用するDBを用意しておいてください。
支障がなければNodeは最新版を入れておけば問題ないはず。
DBは[Sequelizeで使用できるDB](https://sequelize.org/v5/manual/dialects.html)を参照して使用するDB用意しておいてください。
DBの中身を確認するためのクライアントも用意してください。(Sequelなど)

作業フォルダやインストールオプション等は各自の環境に合わせ適当にご対応願います。

## 手順
1. [Expressアプリケーションスケルトン作成](#1expressアプリケーションスケルトン作成)
2. [パッケージインストール](#2パッケージインストール)
3. [Sequelize初期化とconfig確認](#3sequelize初期化とconfig確認)
4. [データベース作成](#4データベース作成)
5. [モデル・マイグレーションファイル作成](#5モデルマイグレーションファイル作成)
6. [マイグレーション実行](#6マイグレーション実行)

### 1.Expressアプリケーションスケルトン作成
ここではExpressアプリケーションスケルトンを作成します。
生成プログラム・ツール「express」を使用すると簡単に作成できます。
インストールしていない場合は、下記コマンドでインストールしましょう。

```bash:ターミナル
npm install express-generator -g
```

expressコマンドで現在のディレクトリにExpressアプリケーションスケルトンを作成します。
今回はAPIサーバーを作成するためviewはいらないので、--no-viewオプションをつけて作成します。
アプリ名はapiAppとしました。

```bash:ターミナル
express --no-view apiApp
```
コマンド実行後、以下のスケルトンが作成され、ターミナル上にログが出力されます。

<details><summary>【参考】作成されたスケルトンとログ</summary>
<div>
作成されたスケルトン
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858634/84bcbf11-4ad2-2794-017d-6581ab4c767a.png"  width="250px">
ログ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858634/e350ca78-aceb-43bb-4358-19abde68f3cc.png"  width="300px">

ログを見てみると、change directory:以下に３つのコマンドが表示されています。

```bash:ターミナル
cd apiApp
npm install
DEBUG=apiapp:* npm start
```

これらを順に実行すると、ローカルサーバーが立ち上がります。

ブラウザでlocalhost:3000にアクセスすれば、

![WelcomExpress.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858634/27c3a2b9-bf99-a88f-a5f4-66e6cee74134.png)

という画面が表示されると思います。
</div>
</details>

---
### 2.パッケージインストール
これから作成していくAPIサーバーアプリで使用するパッケージをインストールしましょう。
アプリのルートディレクトリに移動してから、ターミナルで以下のコマンドを実行していきます。

* Express本体 ( 1でインストールしたのは、スケルトン作成ツールのexpress-generator )

```bash:ターミナル
npm install express --save
```

* Sequelize本体

```bash:ターミナル
npm install sequelize --save
```

* Sequelize CLI ( 今後も使用することを考え、globalにインストールしました。)

```bash:ターミナル
sudo npm install -g sequelize-cli
```

* DB用パッケージ ( 各自のDBに合わせてパッケージを変えてください。これはmysql用です。 )

```bash:ターミナル
npm install mysql2 --save
```

Sequelize CLI からSequelizeを使って、モデル・マイグレーションファイルの作成やマイグレーションなどをターミナルから実行できます。
[Sequelize CLIのRead Me](https://github.com/sequelize/cli) を参照ください。

---

### 3.Sequelize初期化とconfig確認

今回の目的は、Sequelizeを使用して、ユーザーを表すモデルを作成しマイグレーションすることです。
Sequelizeを使用するためには、まずSequelizeの初期化を行います。

まずはアプリのルートフォルダに移動しましょう。
Sequelize CLI を使ってSequelizeを初期化します。
ターミナルで、次のコマンドを実行してください。

```bash:ターミナル
npx sequelize init
```
アプリルートフォルダ内に、

* config
* migrations
* models
* seeders

というフォルダが作成されたことを確認してください。

<details><summary>【参考】フォルダ階層</summary>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858634/144e3398-55c7-7a87-0291-dc7291d19cf5.png"  width="200px">
</details>

モデル作成とマイグレーションを行う前に、configディレクトリ内のconfig.jsonを確認しましょう。
config.jsonにはDBへの接続情報を記述します。
各自の環境に合わせて記述してください。

<details><summary>デフォルトのconfig.json</summary>
<div>

```json:config.json
{
  "development": {
    "username": "root",
    "password": null,
    "database": "database_development",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "test": {
    "username": "root",
    "password": null,
    "database": "database_test",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "production": {
    "username": "root",
    "password": null,
    "database": "database_production",
    "host": "127.0.0.1",
    "dialect": "mysql"
  }
}
```

</div>
</details>

#### 実行環境の指定
config.jsonの３つのキー、development、test、production以下のオブジェクトで実行環境ごとの設定ができます。Sequelizeは環境変数NODE_ENVで指定された値をアプリルート/models/index.jsで読み込み実行します。
デフォルトはdevelopmentになります。

<details><summary>【参考】models/index.js</summary>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858634/40caf4fa-182e-ba2a-4322-7af132ff1d02.png"  width="500px">
</details>

#### DBの指定
Sequelize CLIはデフォルトでmysqlがDBに設定されます。
他のDBを使用する場合は、dialectを編集してください。
[Sequelizeで使用できるDB](https://sequelize.org/v5/manual/dialects.html)

#### ポートの指定
Sequelizeはデフォルトで、5432でDBを扱います。異なるポートを使用したい場合は、該当する環境にportフィールドを追加してください。

---

### 4.データベース作成
ここではSequelizeのdb:createを使用して、config.jsonに基づいたデータベースを作成します。
データベースを作成済の方は、このチャプターは飛ばしてください。

<details><summary>Sequelize CLI のdb:createによるデータベース作成</summary>
<div>
デフォルトのconfig.json(上で記載しているのでご参照ください)を使って、development環境でdb:createを実行し、データベース名：database_developmentというデータベースを作成します。
<br>
まず、環境変数NODE_ENVについて、環境変数一覧を表示して、以下を確認してください。

* 環境変数NODE_ENVがdevelopmentに設定されている、もしくは環境変数にNODE_ENVが設定されていない
* 環境変数NODE_ENVがdevelopment以外のものが設定されている場合は、developmentに設定する

環境変数一覧表示コマンド

```bash:ターミナル
export -p
```

次に、アプリのルートディレクトリに移動して、以下のコマンドを実行します。

```bash:ターミナル
npx sequelize db:create
```

database_developmentというデータベースが作成されたことをDBクライアントで確認してください。

<details><summary>【参考】db:create後のDBクライアント(Sequel)</summary>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858634/901d1d50-9aca-63e8-1ca0-1b5123d47c1f.png"  width="500px">
</details>

</div>
</details>

---

### 5.モデル・マイグレーションファイル作成
では、いよいよユーザーを表すモデルを作成していきます。
ユーザーのモデルとして、氏名だけを持つシンプルなモデルを考えます。

モデル名とテーブル名をどうしようか考えていたところ、公式ドキュメントに以下の記述がありました。

>A model in Sequelize has a name. This name does not have to be the same name of the table it represents in the database. Usually, models have singular names (such as User) while tables have pluralized names (such as Users), although this is fully configurable.

要約すると、
* モデル名とテーブル名は一致している必要はない。
* よく使われるのは、モデルは単数形、テーブル名は複数形というパターン。
* 例えばモデル名：User、テーブル名：とUsersとする。

例にならって、モデル名：Userとしてモデルを作成します。

まず、アプリのルートディレクトリに移動してください。

modelsディレクトリにはindex.jsのみ存在し、migrationsディレクトリは空であることを確認してください。(もちろん他のモデルを作成していた場合、それらのファイルが存在しています。)

そして、次のコマンドを実行します。
Userというモデル名でカラム名がnameというstring型のカラムを持つモデルファイルを生成します。

```bash:ターミナル
npx sequelize model:generate --name User --attributes name:string
```

modelsディレクトリとmigrationsディレクトリに、モデルファイルとマイグレーションファイルがそれぞれ作成されたことを確認してください。

<details><summary>【参考】model:create後のアプリフォルダ</summary>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858634/1978f8eb-3048-2e70-8742-2c61efc2313a.png"  width="300px">
</details>

Sequelizeでは、model:generateするとモデルファイルと共にマイグレーションファイルも生成されます。
モデルファイルやマイグレーションファイルの詳しい内容は次回以降追っていくことにして、少しだけ中身を見てみます。

#### モデルファイル
User.initの中で、モデル名とカラムについての記述があります。

```javascript:user.js抜粋
〜
  User.init({
    name: DataTypes.STRING
  }, {
    sequelize,
    modelName: 'User',
  });
〜
```

#### マイグレーションファイル
Usersとテーブル名を自動で複数形にしてくれています。
id,createdAt,updatedAtはデフォルトで自動で付けてくれます。

```javascript:マイグレーションファイル(○○-create-user.js)抜粋
〜
    await queryInterface.createTable('Users', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      name: {
        type: Sequelize.STRING
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
〜
```

---

### 6.マイグレーション実行
では、マイグレーションを実行してテーブルを作成しましょう。
アプリのルートディレクトリに移動して、次のコマンドを実行してください。

```bash:ターミナル
$ npx sequelize db:migrate
```

処理完了後、DBクライアントからテーブルが作成されたことを確認してください。

<details><summary>【参考】db:migrate後のDBクライアント(Sequel)</summary>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858634/fa4a7950-6a75-f26b-a079-fcd106fd52ef.png"  width="600px">
</details>

---

## 振り返りと次回の話題
今回の内容をざっとまとめると、以下を行いました。

* Expressアプリケーションのスケルトン作成
* Sequelize関連パッケージインストール
* Sequelize-CLIで以下を実行
    * init でSequelizeを初期化し、configファイルを確認
    * db:create でデータベース作成
    * model:generate でUserモデルのモデル・マイグレーションファイル作成
    * db:migrate でマイグレーションを実行してUsersテーブル作成

次回は、ユーザーデータ取得処理、についてまとめる予定です。