Skip to content

Instantly share code, notes, and snippets.

@bendytree
Created October 10, 2014 00:40
Show Gist options
  • Select an option

  • Save bendytree/617f6f85afb27170baa3 to your computer and use it in GitHub Desktop.

Select an option

Save bendytree/617f6f85afb27170baa3 to your computer and use it in GitHub Desktop.
Use standard NodeJS callbacks to validate MongooseJS documents.
/**
* Josh Wright <@BendyTree>
* http://www.joshwright.com
*
* MIT
*
*
* Standard MongooseJS validation looks like this:
*
* schema.path("email").validate(function(val, callback){
* var isValid = /^.+@.+[.].+$/.test(val);
* callback(isValid);
* }, "The email address is invalid.");
*
* It leaves a bit to be desired:
*
* - The callback expects a falsy value if there's an error (the opposite of standard callbacks).
* - The validation must be attached to a path (sometimes validation includes multiple).
* - You cannot customize the error message based on the error.
*
* To use the following validation, you need to extend mongoose like so:
*
* var mongoose = require('mongoose');
* require('./document-validation')(mongoose);
*
* Then you can use standard node callbacks:
*
* var schema = new mongoose.Schema({...});
* schema.addValidator(function(callback){
* callback("Your email address must contain an @ sign.");
* });
*
*/
module.exports = function(mongoose) {
mongoose.Schema.prototype.addValidator = function (validator) {
var schema = this;
var pathKeys = _.keys(schema.paths);
//make sure there is a path we can attach to
if (!pathKeys.length)
throw new Error("Unable to add validator to schema because schema has no keys.");
//add validator using normal path validation
schema.path(pathKeys[0]).validate(function(val, isValidCallback){
//keep track of the doc
var doc = this;
//run the custom validator then adapt the standard callback to Mongoose weirdness
validator.call(doc, function(err){
//if there was an error, call `invalidate` so the error message was maintained
if (err) {
doc.invalidate("", err);
}
//always report that original validation succeeded since it
//doesn't allow us to customize the error message
isValidCallback(true);
});
});
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment