REST APIをバリデーションも踏まえてSequelizeとExpressで作る。

前回、Node.js 向け ORM Sequelize のバリデーションとエラーハンドリングSequelizeのバリデーションを試したので、
Express を絡めた RESTAPI の作成で作成した RESTAPI をバリデーションを踏まえて修正してみます。

目次

実装

前回から引き続き、アクセスするモデルは文字列nameと整数ageを持つUserです。
それぞれのバリデーションの内容は以下の通りです。

  • name
    • null 禁止
    • 空文字列禁止
    • 文字列長を 1~20 に拘束
  • age
    • null 禁止
    • 空文字禁止
    • 整数に拘束
    • 最小値を 12 に拘束
    • 最大値を 100 に拘束

上記に基づいて、設定した User モデルが以下のuser.jsとなります。

models\user.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
"use strict";
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define(
"User",
{
name: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notNull: { msg: 'Please param to "name"' },
notEmpty: { msg: 'Please not enpty param to "name"' },
len: [1, 20],
},
},
age: {
type: DataTypes.INTEGER,
allowNull: false,
validate: {
notNull: { msg: 'Please param "age"' },
notEmpty: { msg: 'Please not enpty param to "age"' },
isInt: true,
min: 12,
max: 100,
},
},
},
{}
);
User.associate = function (models) {};
return User;
};

こちらを呼び出す、Express アプリのコードが以下の通りです。

./src/index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//Express関連読み込み
const express = require(`express`);
const bodyparser = require(`body-parser`);

//モデルを読み込み
const models = require("../models");

//アプリケーション作成
const app = express();
app.use(bodyparser.urlencoded({ extended: false }));
app.use(bodyparser.json());

//アクション:データベースアクセス、レスポンス定義
const index = async (req, res) => {
res.type("json");
models.User.findAll().then((users) => {
res.status(200).send(JSON.stringify(users));
});
};

const show = async (req, res) => {
models.User.findByPk(req.params.id).then((users) => {
res.type("json");
if (users != null) {
res.status(200).send(JSON.stringify(users));
} else {
res.status(404).end();
}
});
};

const create = async (req, res) => {
res.type("json");
models.User.create(req.body)
.then((User) => {
res.status(201).send(JSON.stringify(User));
})
.catch((Err) => {
res.status(400).end(Err.message);
});
};

const update = async (req, res) => {
res.type("json");
models.User.update(req.body, { where: { id: req.params.id } })
.then((result) => {
if (result >= 1) {
res.status(200).end();
} else {
res.status(400).end();
}
})
.catch((Err) => {
res.status(400).end(Err.message);
});
};

const destroy = async (req, res) => {
res.type("json");
models.User.destroy({ where: { id: req.params.id } }).then((result) => {
if (result == 1) {
res.status(204).end();
} else {
res.status(404).end();
}
});
};

//ルーティング定義
app.get("/users", index);
app.post("/users", create);
app.get("/users/:id", show);
app.patch("/users/:id", update);
app.delete("/users/:id", destroy);

//サーバ起動時使用ポート定義
const port = process.argv[2] == null ? 3000 : process.argv[2];

//サーバ開始
app.listen(port);
console.log(`Start Server at ${port}!!`);

こちらをnode src\index.jsで起動します。
適当な REST クライアントでアクセスし、動作確認します。
バリデーションによってはじかれることを確認できるはず。
以前バリデーションが無いために機能しなかった create と update はのエラー処理が機能するようになりました。

一旦ここまで出来れば、シンプルなものは作れそうです。
Rails を挟んで一般的な形を一旦学べたことは Node.js の学習を進めるうえでも非常に良かったです。
次は、複数モデルの関連付けになるのかなと思う次第です。

ではでは