expressでvalidateパッケージをいくつか使ってみた後…(車輪)

車輪の再発明記録です。

expressで、validateのパッケージを探してたんだけど、いくつか試した後、面倒になって自作してしまいました。 今見てみると、express-validatorで問題ないような気もする。。。

viewを簡潔に書きたくて、handlebarsを選択したんけど、これがかなり厳格にviewでロジックを書く事を拒否してるので、viewからカジュアルにメソッド呼び出しもさせてくれなくて、微妙な感じになってしまったのかもしれない。

validate.js

フィールド毎にルールを定義できて、チェック結果を連想配列で返せるのと、チェック関数を提供する。

var Field = function(name){
  this.name = name,
  this.rules = [];
};
Field.prototype.rule = function(fun, message){
  this.rules.push({
    fun: fun,
    message: message
  });
};
var validate = {
  fields: {},
  errors: {},
  field: function (name) {
    if (!(name in this.fields)) {
      this.fields[name] = new Field(name);
    }
    return this.fields[name];
  },
  init: function(){
    this.fields = {};
    this.errors = {};
  },
  isValid: function(req){
    console.log('isValid');
    for (var name in this.fields) {
      var f = this.fields[name];
      var value = req.body[name];
      for (var j = 0; j < f.rules.length; j++) {
        var rule = f.rules[j];
        console.log(rule.fun.toString());
        if (!rule.fun(value)) {
          if (!(name in this.errors)) {
            this.errors[name] = [];
          }
          this.errors[name].push(rule.message);
        }
      }
    }
    return Object.keys(this.errors) == 0;
  },
  required: function(){
    return function(x){
      if (typeof x == 'undefined') {
        return false;
      }
      if (typeof x == 'string') {
        if (x.length == 0) {
          return false;
        }
      }
      return true;
    };
  },
  maxlength: function(n){
    var max = n;
    return function(x){
      console.log(x);
      return x.length <= max;
    };
  },
  notinclude: function(arr){
    var items = arr;
    return function(x){
      for (var i = 0; i < items.length; i++) {
        if (x == items[i]) {
          return false;
        }
      }
      return true;
    };
  },
};
 
 
module.exports = validate;
// vim: set ts=2 sts=2 sw=2 expandtab ai:

routes/index.js

使用例。validate.field() でルールとエラーメッセージを登録している。

var validate = require('../validate');
 
router.post('/register/:id', function(req, res, next) {
 
  var id = req.params.id;
  validate.init();
  validate.field('kamigo').rule(validate.required(), '入力してください。'); 
  validate.field('nakasiti').rule(validate.required(), '入力してください。'); 
  validate.field('simogo').rule(validate.required(), '入力してください。'); 
  if (!validate.isValid(req)) {
    console.log(validate.errors);
    req.flash('error', '入力エラーがあります。');
    return res.render('register', {
      errors: validate.errors,
    });
  }
  ....

views/register.hbs

viewファイル。inputのclassにエラー用クラスを追加するのと、エラーメッセージを表示する。

            <div class="col-lg-3 col-sm-10">
              <input class="form-control {{#if errors.kamigo}}is-invalid{{/if}}" type="text" value="{{req.body.kamigo}}" id="kamigo" name="kamigo" placeholder="五" maxlength="8" >
              <div class="invalid-feedback">
                {{errors.kamigo}}
              </div>
            </div>
            <div class="col-lg-4 col-sm-10">
              <input class="form-control {{#if errors.nakasiti}}is-invalid{{/if}}" type="text" value="{{req.body.nakasiti}}" id="nakasiti" name="nakasiti" placeholder="七" maxlength="10">
              <div class="invalid-feedback">
                {{errors.nakasiti}}
              </div>
            </div>
            <div class="col-lg-3 col-sm-10">
              <input class="form-control {{#if errors.simogo}}is-invalid{{/if}}" type="text" value="{{req.body.simogo}}" id="simogo" name="simogo" placeholder="五" maxlength="8">
              <div class="invalid-feedback">
                {{errors.simogo}}
              </div>
            </div>

express-validator への置き換えを検討した方がいいか。

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.