give options to validators #984
This commit is contained in:
parent
baef033115
commit
35f14c38dc
14
lib/dao.js
14
lib/dao.js
|
@ -320,7 +320,7 @@ DataAccessObject.create = function(data, options, cb) {
|
||||||
} else {
|
} else {
|
||||||
cb(new ValidationError(obj), obj);
|
cb(new ValidationError(obj), obj);
|
||||||
}
|
}
|
||||||
}, data);
|
}, data, options);
|
||||||
});
|
});
|
||||||
|
|
||||||
function create() {
|
function create() {
|
||||||
|
@ -543,7 +543,7 @@ DataAccessObject.upsert = function(data, options, cb) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
callConnector();
|
callConnector();
|
||||||
}, update);
|
}, update, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
function callConnector() {
|
function callConnector() {
|
||||||
|
@ -732,7 +732,7 @@ DataAccessObject.replaceOrCreate = function replaceOrCreate(data, options, cb) {
|
||||||
inst.isValid(function(valid) {
|
inst.isValid(function(valid) {
|
||||||
if (!valid) return cb(new ValidationError(inst), inst);
|
if (!valid) return cb(new ValidationError(inst), inst);
|
||||||
callConnector();
|
callConnector();
|
||||||
}, update);
|
}, update, options);
|
||||||
|
|
||||||
function callConnector() {
|
function callConnector() {
|
||||||
update = removeUndefined(update);
|
update = removeUndefined(update);
|
||||||
|
@ -1002,7 +1002,7 @@ DataAccessObject.findOrCreate = function findOrCreate(query, data, options, cb)
|
||||||
} else {
|
} else {
|
||||||
cb(new ValidationError(obj), obj);
|
cb(new ValidationError(obj), obj);
|
||||||
}
|
}
|
||||||
}, data);
|
}, data, options);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -2189,7 +2189,7 @@ DataAccessObject.prototype.save = function(options, cb) {
|
||||||
}
|
}
|
||||||
cb(err, inst);
|
cb(err, inst);
|
||||||
}
|
}
|
||||||
});
|
}, data, options);
|
||||||
|
|
||||||
// then save
|
// then save
|
||||||
function save() {
|
function save() {
|
||||||
|
@ -2694,7 +2694,7 @@ DataAccessObject.replaceById = function(id, data, options, cb) {
|
||||||
if (!valid) return cb(new ValidationError(inst), inst);
|
if (!valid) return cb(new ValidationError(inst), inst);
|
||||||
|
|
||||||
callConnector();
|
callConnector();
|
||||||
}, data);
|
}, data, options);
|
||||||
} else {
|
} else {
|
||||||
callConnector();
|
callConnector();
|
||||||
}
|
}
|
||||||
|
@ -2874,7 +2874,7 @@ function(data, options, cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
triggerSave();
|
triggerSave();
|
||||||
}, data);
|
}, data, options);
|
||||||
} else {
|
} else {
|
||||||
triggerSave();
|
triggerSave();
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,7 +238,7 @@ Validatable.validatesUniquenessOf = getConfigurator('uniqueness', { async: true
|
||||||
/*!
|
/*!
|
||||||
* Presence validator
|
* Presence validator
|
||||||
*/
|
*/
|
||||||
function validatePresence(attr, conf, err) {
|
function validatePresence(attr, conf, err, options) {
|
||||||
if (blank(this[attr])) {
|
if (blank(this[attr])) {
|
||||||
err();
|
err();
|
||||||
}
|
}
|
||||||
|
@ -247,7 +247,7 @@ function validatePresence(attr, conf, err) {
|
||||||
/*!
|
/*!
|
||||||
* Absence validator
|
* Absence validator
|
||||||
*/
|
*/
|
||||||
function validateAbsence(attr, conf, err) {
|
function validateAbsence(attr, conf, err, options) {
|
||||||
if (!blank(this[attr])) {
|
if (!blank(this[attr])) {
|
||||||
err();
|
err();
|
||||||
}
|
}
|
||||||
|
@ -256,7 +256,7 @@ function validateAbsence(attr, conf, err) {
|
||||||
/*!
|
/*!
|
||||||
* Length validator
|
* Length validator
|
||||||
*/
|
*/
|
||||||
function validateLength(attr, conf, err) {
|
function validateLength(attr, conf, err, options) {
|
||||||
if (nullCheck.call(this, attr, conf, err)) return;
|
if (nullCheck.call(this, attr, conf, err)) return;
|
||||||
|
|
||||||
var len = this[attr].length;
|
var len = this[attr].length;
|
||||||
|
@ -274,7 +274,7 @@ function validateLength(attr, conf, err) {
|
||||||
/*!
|
/*!
|
||||||
* Numericality validator
|
* Numericality validator
|
||||||
*/
|
*/
|
||||||
function validateNumericality(attr, conf, err) {
|
function validateNumericality(attr, conf, err, options) {
|
||||||
if (nullCheck.call(this, attr, conf, err)) return;
|
if (nullCheck.call(this, attr, conf, err)) return;
|
||||||
|
|
||||||
if (typeof this[attr] !== 'number') {
|
if (typeof this[attr] !== 'number') {
|
||||||
|
@ -288,7 +288,7 @@ function validateNumericality(attr, conf, err) {
|
||||||
/*!
|
/*!
|
||||||
* Inclusion validator
|
* Inclusion validator
|
||||||
*/
|
*/
|
||||||
function validateInclusion(attr, conf, err) {
|
function validateInclusion(attr, conf, err, options) {
|
||||||
if (nullCheck.call(this, attr, conf, err)) return;
|
if (nullCheck.call(this, attr, conf, err)) return;
|
||||||
|
|
||||||
if (!~conf.in.indexOf(this[attr])) {
|
if (!~conf.in.indexOf(this[attr])) {
|
||||||
|
@ -299,7 +299,7 @@ function validateInclusion(attr, conf, err) {
|
||||||
/*!
|
/*!
|
||||||
* Exclusion validator
|
* Exclusion validator
|
||||||
*/
|
*/
|
||||||
function validateExclusion(attr, conf, err) {
|
function validateExclusion(attr, conf, err, options) {
|
||||||
if (nullCheck.call(this, attr, conf, err)) return;
|
if (nullCheck.call(this, attr, conf, err)) return;
|
||||||
|
|
||||||
if (~conf.in.indexOf(this[attr])) {
|
if (~conf.in.indexOf(this[attr])) {
|
||||||
|
@ -310,7 +310,7 @@ function validateExclusion(attr, conf, err) {
|
||||||
/*!
|
/*!
|
||||||
* Format validator
|
* Format validator
|
||||||
*/
|
*/
|
||||||
function validateFormat(attr, conf, err) {
|
function validateFormat(attr, conf, err, options) {
|
||||||
if (nullCheck.call(this, attr, conf, err)) return;
|
if (nullCheck.call(this, attr, conf, err)) return;
|
||||||
|
|
||||||
if (typeof this[attr] === 'string') {
|
if (typeof this[attr] === 'string') {
|
||||||
|
@ -325,14 +325,22 @@ function validateFormat(attr, conf, err) {
|
||||||
/*!
|
/*!
|
||||||
* Custom validator
|
* Custom validator
|
||||||
*/
|
*/
|
||||||
function validateCustom(attr, conf, err, done) {
|
function validateCustom(attr, conf, err, options, done) {
|
||||||
|
if (typeof options === 'function') {
|
||||||
|
done = options;
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
conf.customValidator.call(this, err, done);
|
conf.customValidator.call(this, err, done);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Uniqueness validator
|
* Uniqueness validator
|
||||||
*/
|
*/
|
||||||
function validateUniqueness(attr, conf, err, done) {
|
function validateUniqueness(attr, conf, err, options, done) {
|
||||||
|
if (typeof options === 'function') {
|
||||||
|
done = options;
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
if (blank(this[attr])) {
|
if (blank(this[attr])) {
|
||||||
return process.nextTick(done);
|
return process.nextTick(done);
|
||||||
}
|
}
|
||||||
|
@ -349,7 +357,7 @@ function validateUniqueness(attr, conf, err, done) {
|
||||||
|
|
||||||
var idName = this.constructor.definition.idName();
|
var idName = this.constructor.definition.idName();
|
||||||
var isNewRecord = this.isNewRecord();
|
var isNewRecord = this.isNewRecord();
|
||||||
this.constructor.find(cond, function(error, found) {
|
this.constructor.find(cond, options, function(error, found) {
|
||||||
if (error) {
|
if (error) {
|
||||||
err(error);
|
err(error);
|
||||||
} else if (found.length > 1) {
|
} else if (found.length > 1) {
|
||||||
|
@ -416,7 +424,8 @@ function getConfigurator(name, opts) {
|
||||||
* @param {Function} callback called with (valid)
|
* @param {Function} callback called with (valid)
|
||||||
* @returns {Boolean} True if no asynchronous validation is configured and all properties pass validation.
|
* @returns {Boolean} True if no asynchronous validation is configured and all properties pass validation.
|
||||||
*/
|
*/
|
||||||
Validatable.prototype.isValid = function(callback, data) {
|
Validatable.prototype.isValid = function(callback, data, options) {
|
||||||
|
options = options || {};
|
||||||
var valid = true, inst = this, wait = 0, async = false;
|
var valid = true, inst = this, wait = 0, async = false;
|
||||||
var validations = this.constructor.validations;
|
var validations = this.constructor.validations;
|
||||||
|
|
||||||
|
@ -455,7 +464,7 @@ Validatable.prototype.isValid = function(callback, data) {
|
||||||
async = true;
|
async = true;
|
||||||
wait += 1;
|
wait += 1;
|
||||||
process.nextTick(function() {
|
process.nextTick(function() {
|
||||||
validationFailed(inst, attr, v, done);
|
validationFailed(inst, attr, v, options, done);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (validationFailed(inst, attr, v)) {
|
if (validationFailed(inst, attr, v)) {
|
||||||
|
@ -514,9 +523,14 @@ function cleanErrors(inst) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function validationFailed(inst, attr, conf, cb) {
|
function validationFailed(inst, attr, conf, options, cb) {
|
||||||
var opts = conf.options || {};
|
var opts = conf.options || {};
|
||||||
|
|
||||||
|
if (typeof options === 'function') {
|
||||||
|
cb = options;
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof attr !== 'string') return false;
|
if (typeof attr !== 'string') return false;
|
||||||
|
|
||||||
// here we should check skip validation conditions (if, unless)
|
// here we should check skip validation conditions (if, unless)
|
||||||
|
@ -557,6 +571,7 @@ function validationFailed(inst, attr, conf, cb) {
|
||||||
if (kind !== false) inst.errors.add(attr, message, code);
|
if (kind !== false) inst.errors.add(attr, message, code);
|
||||||
fail = true;
|
fail = true;
|
||||||
});
|
});
|
||||||
|
validatorArguments.push(options);
|
||||||
if (cb) {
|
if (cb) {
|
||||||
validatorArguments.push(function() {
|
validatorArguments.push(function() {
|
||||||
cb(fail);
|
cb(fail);
|
||||||
|
|
|
@ -282,6 +282,64 @@ describe('validations', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('validation with or without options', function() {
|
||||||
|
it('should work on update with options', function(done) {
|
||||||
|
delete User.validations;
|
||||||
|
User.validatesPresenceOf('name');
|
||||||
|
User.create({ name: 'Valid' }, function(e, d) {
|
||||||
|
d.updateAttribute('name', null, { options: 'options' }, function(e) {
|
||||||
|
should.exist(e);
|
||||||
|
e.should.be.instanceOf(Error);
|
||||||
|
e.should.be.instanceOf(ValidationError);
|
||||||
|
d.updateAttribute('name', 'Vasiliy', { options: 'options' }, function(e) {
|
||||||
|
should.not.exist(e);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work on update without options', function(done) {
|
||||||
|
delete User.validations;
|
||||||
|
User.validatesPresenceOf('name');
|
||||||
|
User.create({ name: 'Valid' }, function(e, d) {
|
||||||
|
d.updateAttribute('name', null, function(e) {
|
||||||
|
should.exist(e);
|
||||||
|
e.should.be.instanceOf(Error);
|
||||||
|
e.should.be.instanceOf(ValidationError);
|
||||||
|
d.updateAttribute('name', 'Vasiliy', function(e) {
|
||||||
|
should.not.exist(e);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work on create with options', function(done) {
|
||||||
|
delete User.validations;
|
||||||
|
User.validatesPresenceOf('name');
|
||||||
|
User.create(function(e, u) {
|
||||||
|
should.exist(e);
|
||||||
|
User.create({ name: 'Valid' }, { options: 'options' }, function(e, d) {
|
||||||
|
should.not.exist(e);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work on create without options', function(done) {
|
||||||
|
delete User.validations;
|
||||||
|
User.validatesPresenceOf('name');
|
||||||
|
User.create(function(e, u) {
|
||||||
|
should.exist(e);
|
||||||
|
User.create({ name: 'Valid' }, function(e, d) {
|
||||||
|
should.not.exist(e);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('presence', function() {
|
describe('presence', function() {
|
||||||
it('should validate presence', function() {
|
it('should validate presence', function() {
|
||||||
User.validatesPresenceOf('name', 'email');
|
User.validatesPresenceOf('name', 'email');
|
||||||
|
|
Loading…
Reference in New Issue