Rewrite custom validation

This commit is contained in:
Anatoliy Chakkaev 2011-11-19 01:59:46 +07:00
parent e55b29e479
commit 9dcd976546
3 changed files with 39 additions and 30 deletions

View File

@ -10,17 +10,7 @@ Validatable.validatesNumericalityOf = getConfigurator('numericality');
Validatable.validatesInclusionOf = getConfigurator('inclusion'); Validatable.validatesInclusionOf = getConfigurator('inclusion');
Validatable.validatesExclusionOf = getConfigurator('exclusion'); Validatable.validatesExclusionOf = getConfigurator('exclusion');
Validatable.validatesFormatOf = getConfigurator('format'); Validatable.validatesFormatOf = getConfigurator('format');
Validatable.validate = function () { Validatable.validate = getConfigurator('custom');
args = [].slice.call(arguments);
var valFn = function () {}; // noop
if (typeof args[args.length - 1] === 'function'){
valFn = args.pop();
}
wrapperFn = function customValidator(attr, conf, err) {
return valFn.call(this, err);
};
configure(this, wrapperFn, args)
};
// implementation of validators // implementation of validators
var validators = { var validators = {
@ -77,13 +67,16 @@ var validators = {
} else { } else {
err(); err();
} }
},
custom: function (attr, conf, err) {
conf.customValidator.call(this, err);
} }
}; };
function getConfigurator(name) { function getConfigurator(name, opts) {
return function () { return function () {
configure(this, name, arguments); configure(this, name, arguments, opts);
}; };
} }
@ -124,6 +117,9 @@ function cleanErrors(inst) {
function validationFailed(inst, v) { function validationFailed(inst, v) {
var attr = v[0]; var attr = v[0];
var conf = v[1]; var conf = v[1];
var opts = v[2] || {};
if (typeof attr !== 'string') return false;
// here we should check skip validation conditions (if, unless) // here we should check skip validation conditions (if, unless)
// that can be specified in conf // that can be specified in conf
@ -131,8 +127,11 @@ function validationFailed(inst, v) {
if (skipValidation(inst, conf, 'unless')) return false; if (skipValidation(inst, conf, 'unless')) return false;
var fail = false; var fail = false;
var validator = typeof conf.validation === "function" ? conf.validation : validators[conf.validation]; var validator = validators[conf.validation];
validator.call(inst, attr, conf, function onerror(kind) { var validatorArguments = [];
validatorArguments.push(attr);
validatorArguments.push(conf);
validatorArguments.push(function onerror(kind) {
var message; var message;
if (conf.message) { if (conf.message) {
message = conf.message; message = conf.message;
@ -154,6 +153,7 @@ function validationFailed(inst, v) {
inst.errors.add(attr, message); inst.errors.add(attr, message);
fail = true; fail = true;
}); });
validator.apply(inst, validatorArguments);
return fail; return fail;
} }
@ -221,7 +221,7 @@ function blank(v) {
return false; return false;
} }
function configure(cls, validation, args) { function configure(cls, validation, args, opts) {
if (!cls._validations) { if (!cls._validations) {
Object.defineProperty(cls, '_validations', { Object.defineProperty(cls, '_validations', {
writable: true, writable: true,
@ -237,9 +237,12 @@ function configure(cls, validation, args) {
} else { } else {
conf = {}; conf = {};
} }
if (validation === 'custom' && typeof args[args.length - 1] === 'function') {
conf.customValidator = args.pop();
}
conf.validation = validation; conf.validation = validation;
args.forEach(function (attr) { args.forEach(function (attr) {
cls._validations.push([attr, conf]); cls._validations.push([attr, conf, opts]);
}); });
} }
@ -253,3 +256,4 @@ Errors.prototype.add = function (field, message) {
this[field].push(message); this[field].push(message);
} }
}; };

View File

@ -77,3 +77,4 @@ it "should trigger after destroy", (test)->
test.done() test.done()
User.create {}, (err, user)-> User.create {}, (err, user)->
user.destroy() user.destroy()

View File

@ -214,16 +214,20 @@ it 'should validate format', (test) ->
test.done() test.done()
it 'should validate a field using a custom validator', (test)-> it 'should validate a field using a custom validator', (test) ->
User.validate 'email', (err)-> err("crash") if @email.length is 0 validator = (err) ->
err('crash') if @name == 'bad name'
User.validate 'name', validator, message: crash: 'custom message'
user = new User validAttributes user = new User validAttributes
test.ok user.isValid() test.ok user.isValid()
user = new User validAttributes user = new User validAttributes
user.email = "" user.name = 'bad name'
test.ok not user.isValid() test.ok not user.isValid(), 'invalid due custom name validator'
test.equal user.errors.name[0], 'custom message'
test.done() test.done()