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

View File

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

View File

@ -214,16 +214,20 @@ it 'should validate format', (test) ->
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
test.ok user.isValid()
user = new User validAttributes
user.email = ""
test.ok not user.isValid()
user.name = 'bad name'
test.ok not user.isValid(), 'invalid due custom name validator'
test.equal user.errors.name[0], 'custom message'
test.done()