Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom (user-friendly) ValidatorError message

I'm really new to mongoose, so I was wondering if there is some way to set custom error message instead of default one like Validator "required" failed for path password.

I would like to set something like Password is required. which is more user-friendly.

I wrote some custom validators and set type property with this user-friendly error message, but I'm not sure type is right placeholder for error message. also there is no way to set custom message on predefined validators like min, max, required, enum...

One solution is to check every time type property of error thrown and manually assign error message, but think that's validator's job:

save model
    if error
        check error type (eg. "required")
        assign fancy error message (eg. "Password is required.")

This obviously isn't ideal solution.

I looked at express-form and node-validator but still want to use mongoose validation feature.

like image 231
ManInTheBox Avatar asked Jan 24 '12 12:01

ManInTheBox


1 Answers

I generally use a helper function for such things. Just mocked this one up to be a little more general than then ones I use. This guy will take all of the "default" validators (required, min, max, etc.) and make their messages a little prettier (according to the messages object below), and extract just the message that you passed in your validator for custom validations.

function errorHelper(err, cb) {
    //If it isn't a mongoose-validation error, just throw it.
    if (err.name !== 'ValidationError') return cb(err);
    var messages = {
        'required': "%s is required.",
        'min': "%s below minimum.",
        'max': "%s above maximum.",
        'enum': "%s not an allowed value."
    };

    //A validationerror can contain more than one error.
    var errors = [];

    //Loop over the errors object of the Validation Error
    Object.keys(err.errors).forEach(function (field) {
        var eObj = err.errors[field];

        //If we don't have a message for `type`, just push the error through
        if (!messages.hasOwnProperty(eObj.type)) errors.push(eObj.type);

        //Otherwise, use util.format to format the message, and passing the path
        else errors.push(require('util').format(messages[eObj.type], eObj.path));
    });

    return cb(errors);
}

And it can be used like this (express router example):

function (req, res, next) {
    //generate `user` here
    user.save(function (err) {
        //If we have an error, call the helper, return, and pass it `next`
        //to pass the "user-friendly" errors to
        if (err) return errorHelper(err, next);
    }
}

Before:

{ message: 'Validation failed',
  name: 'ValidationError',
  errors: 
   { username: 
      { message: 'Validator "required" failed for path username',
        name: 'ValidatorError',
        path: 'username',
        type: 'required' },
     state: 
      { message: 'Validator "enum" failed for path state',
        name: 'ValidatorError',
        path: 'state',
        type: 'enum' },
     email: 
      { message: 'Validator "custom validator here" failed for path email',
        name: 'ValidatorError',
        path: 'email',
        type: 'custom validator here' },
     age: 
      { message: 'Validator "min" failed for path age',
        name: 'ValidatorError',
        path: 'age',
        type: 'min' } } }

After:

[ 'username is required.',
  'state not an allowed value.',
  'custom validator here',
  'age below minimum.' ]

Edit: Snap, just realized this was a CoffeeScript question. Not being a CoffeeScript guy, I wouldn't really want to rewrite this in CS. You could always just require it as a js file into your CS?

like image 51
clarkf Avatar answered Oct 16 '22 21:10

clarkf