Node.js Tips: express-validatorの最新バージョンで発生するType Errorの解消方法

Node.js

私が参考にしているNode.jsの参考書籍に記載されているexpress-validatorの使い方と、2021年2月19日時点でのexpress-validator最新バージョン6.9.2ではすでに仕様が異なっており、書籍そのままではTypeErrorとなり実行出来ませんでした。
express-validatorの公式ドキュメントを参考に解決した方法を紹介します。

express-validator公式サイト(github)

やりたいこと

参考書籍に記載されていたコードの抜粋&簡易化したものを掲載し、やりたかったことを説明します。
express-generatorで作成したプロジェクトで、テンプレートエンジンはejs、メイン処理はapp.jsファイルに記載されています。

本記事は以下参考書籍のChapter6を参考にしています。

[広告]

プログラムの概要

‘/’ にアクセスするとformのあるページが表示され、NAME, MAIL, AGEという3つのユーザー情報を入力するフォームが表示されます。
これら3つの情報を入力後にsubmitすると、各値のバリデーションチェックが行われ、問題なければDBに登録されるというものです。
バリデーションチェックの内容は以下の通りで、これらのバリデーションの実装がちゃんと想定どおりに動くことを確認したいというのがやりたいことです。

  • NAME : 空文字ではないこと
  • MAIL : メールアドレス形式の文字列であること
  • AGE : 数値であること

express-validatorの宣言

app.jsで生成しているexpressインスタンスにexpress-validatorを追加します。

var express = require('express');
var indexRouter = require('/routes/index.js');
var addRouter = require('./routes/add.js');
var validator = require('express-validator');
...中略...
var app = express();
app.use(validator());
app.use('/', indexRouter);
app.use('/add', addRouter);

ブラウザからアクセスする際には’/’(./routes/index.js)にアクセスし、そのフォームに定義されているName, Mail, Ageを登録するという前提です。
フォームのアクションで’/add’(./routes/add.js)にアクセスし、そこでバリデーションチェックを行います。

バリデーションチェックの対象とするform要素の定義

index.ejsにform要素を追加します。
これらをバリデーションチェック対象とします。

<p><%- content %></p>
<form method="post" action="/add">
  <table>
    <tr><th>NAME</th><td><input type="text" name="name" value="<%= form.name %>"></td></tr>
    <tr><th>MAIL</th><td><input type="text" name="mail" value="<%= form.mail %>"></td></tr>
    <tr><th>AGE</th><td><input type="text" name="age" value="<%= form.age %>"></td></tr>
    <tr><th></th><td><input type="submit" value="作成"></td></tr>
  </table>
</form>

対象処理へのバリデーションチェック処理の追加

‘/add’(./routes/add.js)にpostでアクセスしたときの処理を追加します。

var express = require('express');
var router = express.Router();

router.post("/add", (req, res, next) => {
  req.check('name', 'NAME は必ず入力してください').notEmpty();
  req.check('mail', 'MAIL はメールアドレスを記入してください').isMail();
  req.check('age', 'AGE は年齢(整数)を入力ください').isInt();

  req.getValidationResult().then((result) => {
    if (!result.isEmpty()) {
      // バリデーションエラーがあった場合の処理
    } else {
      // バリデーションエラーが無かった場合の処理
    }
  });
});

事象

これを実行すると、実行直後に以下のランタイムエラーが発生します。

app.use(validator());
        ^
TypeError: validator is not a function

原因

Express-Validatorの6.9.2(この記事を書いている当時の最新バージョン)の公式ドキュメントでは、このような使い方は想定されていませんでした。
よって、おそらく参考書籍執筆時のExpress-Validatorのバージョンと、私が学習したときに使用したExpress-Validatorのバージョンで、仕様変更があったというのが原因のようです。

対応方法

以下2点を変更して対応することで解決しました。

  • express-validatorのインスタンス生成方法を変更
  • バリデーションチェック方法を変更

以下詳細を説明します。

インスタンス生成方法の変更

Express-Validatorのインスタンスを生成するコードをapp.jsから削除し、各ハンドラーで生成するようにしますが、バリデーションチェックを定義するためのインスタンス「check」と、バリデーション処理を実行し結果を返すインスタンス「validationResult」の2つを生成します。

以下、./routes/add.jsです。

var express = require('express');
// ここにexpress-validatorの宣言を追加する。
var { check, validationResult } = requre('express-validator');
var router = express.Router();

バリデーションチェック方法の変更

バリデーションチェック処理の定義はreqオブジェクトのcheck 関数で定義していましたが、これもTypeError(function is not defined)になります。
postメソッドのハンドラー関数へのパラメータとしてcheck関数で定義します。
そして、バリデーションの実際のチェック処理はvalidationResult関数で実行し、結果を確認します。

router.post("/add", 
  // チェック処理はここで定義する。
  check('name', 'NAME は必ず入力してください').notEmpty(),
  check('mail', 'MAIL はメールアドレスを記入してください').isMail(),
  check('age', 'AGE は年齢(整数)を入力ください').isInt(),
  (req, res, next) => {

    // バリデーションチェックはここで実行し、エラーをチェックする。
    const error =validationResult(req);
    if (!error.isEmpty()) {
      // エラーが空ではない(→エラーが有る)場合の処理
    } else {
      // エラーが空(→エラーがない)場合の処理
    }
  });
});

まとめ

本記事にあるように、書籍は出版日によって内容が陳腐化している可能性があるため、エラーが発生した場合はある程度自力で回答を見つけ出すということが必要になる場合があります。

ですが、これらの確認/調査の活動を通して、私はExpress-Validatorの最新バージョンのドキュメントの読み方を理解し、そして仕様を理解することが出来ました。
これらのことは今後自分でプログラムを発展させていく上で重要なスキルになると思います。
皆さんも、勉強中に書籍に書いてあることなのにうまく動かない等ある場合は諦めずに自分で調査・確認することにチャレンジしてみてください。

コメント

タイトルとURLをコピーしました