『Node.js 超入門』の express-validation を最新の仕様に修正する

# 概要

[Node.js 超入門（第2版）](https://www.shuwasystem.co.jp/book/9784798055220.html) を読んでいたところ、バリデーションの箇所が本の通り書いているにも関わらずエラーが発生。 [正誤表](https://www.shuwasystem.co.jp/support/download/5522/Seigohyo.pdf) を確認したところ、以下のような説明がありました。

> 本書で使用している Express Validator は、現在 ver.6 となり、仕様が変更されているため、本書の記述の通りでは正常に動作しなくなっています。

ver.5 にバージョンダウンすることでサンプルコードのまま実行することが出来たのですが、折角なので最新バージョンに修正して実行をしてみました。
本記事では、[express-validator公式ドキュメント](https://express-validator.github.io/docs/)を参考に行った修正内容について紹介したいと思います。

# 修正内容

## サンプルコード(ver.5 の書き方)

- P.334～335 リスト6-4 より、修正の必要があるPOST時の処理について抜粋  
※修正後と形式を統一するためフォーマッタで一部書き方等を修正してます

```hello.js
router.post("/add", (req, res, next) => {
  req.check("name", "NAME は必ず入力して下さい。").notEmpty();
  req.check("mail", "MAIL はメールアドレスを記入して下さい。").isEmail();
  req.check("age", "AGE は年齢（整数）を入力下さい。").isInt();

  req.getValidationResult().then(result => {
    if (!result.isEmpty()) {
      var re = '<ul class="error">';
      var result_arr = result.array();
      for (var n in result_arr) {
        re += "<li>" + result_arr[n].msg + "</li>";
      }
      re += "</ul>";
      var data = {
        title: "Hello/Add",
        content: re,
        form: req.body
      };
      res.render("hello/add", data);
    } else {
      var nm = req.body.name;
      var ml = req.body.mail;
      var ag = req.body.age;
      var data = { name: nm, mail: ml, age: ag };

      var connection = mysql.createConnection(mysql_setting);
      connection.connect();
      connection.query("insert into mydata set ?", data, function(
        error,
        results,
        fields
      ) {
        res.redirect("/hello");
      });
      connection.end();
    }
  });
});
```

## 修正後コード(ver.6 の書き方)

- express-validationの最新バージョン（記事作成時は6.4.0）で実行できるようPOST処理を修正  
※バリデーション設定箇所以外にも今時のJavaScriptの書き方に変更している箇所もあります（varでなくconstかletで変数を宣言するなど）

```hello.js
const { check, validationResult } = require("express-validator");

router.post(
  "/add",
  [
    check("name")
      .not()
      .isEmpty()
      .withMessage("NAME は必ず入力して下さい。"),
    check("mail")
      .isEmail()
      .withMessage("MAIL はメールアドレスを記入して下さい。"),
    check("age")
      .isInt()
      .withMessage("AGE は年齢(整数)を入力して下さい。")
  ],
  (req, res, next) => {
    const results = validationResult(req);
    if (!results.isEmpty()) {
      let re = "<ul class='error'>";
      const result_arr = results.array();
      for (const err of result_arr) {
        re += `<li>${err.msg}</li>`;
      }
      re += "</ul>";
      const data = {
        title: "Hello/Add",
        content: re,
        form: req.body
      };
      res.render("hello/add", data);
    } else {
      const name = req.body.name;
      const mail = req.body.mail;
      const age = req.body.age;
      const data = { name, mail, age };

      const connection = mysql.createConnection(mysql_setting);
      connection.connect();

      connection.query(
        "INSERT INTO mydata SET ?",
        data,
        (error, results, fields) => {
          if (error === null) {
            res.redirect("/hello");
          }
        }
      );

      connection.end();
    }
  }
);
```

## 修正概要

今回でexpress-validationを使った処理に関しては以下の部分を修正しています

- `require`によるモジュールのロードを`app.js`ではなく`hello.js`の冒頭で行う
  - サンプルの通り`app.js`で宣言した場合には『TypeError: check is not a function』が発生するため変更
  - エラー原因は調査しましたがわからなかったので、ご存知の方がいましたらコメントで教えていただけたら幸いです
- `check`内容を`post`メソッドの第2引数に記載
- ver.5 ではエラー情報を`req.getValidationResult().then()`で`result`を引数としてコールバック関数で処理していたが、ver.6では`validationResult(req)`を定数`result`に代入し、関数の中でその値を使って処理
- `notEmpty()`はなくなっているので、`not().isEmpty()`のように宣言
- エラーメッセージは`withMessage()`をメソッドチェーンにして使用し設定

# まとめ

以上のように修正することで、記事作成時の最新バージョン（ver.6.4.0）のexpress-validatorでもバリデーションを実行することができました。
よかったら参考にしてみて下さい。