3

Express と Mongoose を使用して、ユーザーが新しいアイテムをコレクションに追加できる単純なフォームを作成しようとしています。

マングースのスキーマ:

var Item = new Schema({
  name   : {type : String, required : true},
  price  : {type : Number, required : true},
  description : {type: String, required: true},
});

特急ルート:

var create = function(req, res) {
  Item.create(req.body, function(err) {
    if (err) return res.render('admin/items/new', {title: "New Item", errors: _.values(err.errors)});
    res.redirect('/admin/items/index');
  });
};

これまでのところ十分に単純です。私がやりたいことは、適切な検証を追加priceして、ユーザーが入力したものが数値であることを確認し、そうでない場合は適切なエラーを表示することです。

上記のコードでは、ユーザーが価格テキスト フィールドに数字以外の文字を入力すると、CastError がスローされます。

そのため、スキーマに次の検証を追加しようとしました。

Item.path('price').validate(function(v, fn) {
  if (typeof v === 'number' || v === undefined) return fn(true);
  return fn(false);
}, "must-be-numeric");

ただし、Mongoose はこの検証を適用する前に値をキャストしようとするようです。そのため、これに対して適切な検証エラーを返すことはできず、CastError が返されるだけです。さらに、CastError は、他のフィールドの検証チェックが実行されるのを防ぎます。

私がやろうとしていることはかなり一般的だと思います (Rails ではvalidate :price, :numericality => true、モデルに追加するだけで済みます)。

この種の型検証を容易にする、私が見逃している明らかなパターンはありますか?

他の人はどのようにこれを行いますか?


私が試したこと/考えたこと:

  • node-validator などの二次検証ライブラリを使用して、フォーム フィールドを Mongoose に渡す前に「事前検証」できることを認識しています。ただし、コードの重複や、2 つのバリデーターからのエラー オブジェクトを組み合わせてユーザーにフィードバックされる 1 つのエラー セットを生成するボイラープレートの混乱は、私は本当に望んでいません。
  • 理想的には、HTML5 の "number"input要素を使用して、誤ったユーザー入力を防止したいのですが、Firefox と IE がそれをサポートしていないことを考えると、まだ初心者ではありません。
4

3 に答える 3

3

Mongoose ミドルウェアはあなたの友達です。

Item.pre('save' function(next) {
  if (this.price) {
    if (!myValidationFunction(this.price)) {
      return next(new Error('Price must be yada yada yada'))    
    }
  }
  next()
})

pre('save' ... イベントは、マングースレベルの検証の前に発生するため、エラーの生成方法をより詳細に制御できます。次に、キャッチされていないすべてのエラーをトラップし、エラーをフォーマットする一般的なエラー処理ミドルウェアをエクスプレスで設定しますExpress 2.x には .on('error'... イベントがありましたが、Express 3 では削除されました。

本質的にエラートラップミドルウェアはこのようなことをします

app.use(function(err, req, res, next) {
  if (!(err instanceof Error)) next()
  // First param was some kind of error
  // format and send err.message however you like
  // in dev mode err.stack is usually interesting
  // this code is usually terminal, and does not call next()

}))

十分に文書化されていないマングースミドルウェアを使用する際のいくつかのトリック:

まず、保存を失敗させるには、単純に Error オブジェクトを next に渡します。データベースは変更されません。次に、this.isNew プロパティを確認することで、挿入と更新を区別できます。

このようなパターンを使用する利点の 1 つは、ほとんどの一般的なノード ライブラリで使用されていることです。そのため、エラー処理を統合して、何らかの問題が発生したとしても、妥当なものをフォーマットする機会を得ることができます。

最後に、このアプローチを一般的に採用すると、node.js に独自のカスタム Error オブジェクトを作成したくなるかもしれません。これらはうまく機能しますが、セットアップが少し難しいです。ここに良い記事があります: http://dustinsenos.com/articles/customErrorsInNode

それが役立つことを願っています!

于 2012-07-17T00:07:33.987 に答える