Skip to content

Commit fbe58f7

Browse files
robinbiondiRaymond Feng
authored andcommitted
give options to validators #984
1 parent e0a6828 commit fbe58f7

File tree

3 files changed

+93
-20
lines changed

3 files changed

+93
-20
lines changed

lib/dao.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ DataAccessObject.create = function(data, options, cb) {
320320
} else {
321321
cb(new ValidationError(obj), obj);
322322
}
323-
}, data);
323+
}, data, options);
324324
});
325325

326326
function create() {
@@ -539,7 +539,7 @@ DataAccessObject.upsert = function(data, options, cb) {
539539
}
540540
}
541541
callConnector();
542-
}, update);
542+
}, update, options);
543543
}
544544

545545
function callConnector() {
@@ -723,7 +723,7 @@ DataAccessObject.replaceOrCreate = function replaceOrCreate(data, options, cb) {
723723
inst.isValid(function(valid) {
724724
if (!valid) return cb(new ValidationError(inst), inst);
725725
callConnector();
726-
}, update);
726+
}, update, options);
727727

728728
function callConnector() {
729729
update = removeUndefined(update);
@@ -990,7 +990,7 @@ DataAccessObject.findOrCreate = function findOrCreate(query, data, options, cb)
990990
} else {
991991
cb(new ValidationError(obj), obj);
992992
}
993-
}, data);
993+
}, data, options);
994994
});
995995
});
996996
} else {
@@ -2199,7 +2199,7 @@ DataAccessObject.prototype.save = function(options, cb) {
21992199
}
22002200
cb(err, inst);
22012201
}
2202-
});
2202+
}, data, options);
22032203

22042204
// then save
22052205
function save() {
@@ -2706,7 +2706,7 @@ DataAccessObject.replaceById = function(id, data, options, cb) {
27062706
if (!valid) return cb(new ValidationError(inst), inst);
27072707

27082708
callConnector();
2709-
}, data);
2709+
}, data, options);
27102710
} else {
27112711
callConnector();
27122712
}
@@ -2892,7 +2892,7 @@ function(data, options, cb) {
28922892
}
28932893

28942894
triggerSave();
2895-
}, data);
2895+
}, data, options);
28962896
} else {
28972897
triggerSave();
28982898
}

lib/validations.js

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ Validatable.validatesUniquenessOf = getConfigurator('uniqueness', { async: true
238238
/*!
239239
* Presence validator
240240
*/
241-
function validatePresence(attr, conf, err) {
241+
function validatePresence(attr, conf, err, options) {
242242
if (blank(this[attr])) {
243243
err();
244244
}
@@ -247,7 +247,7 @@ function validatePresence(attr, conf, err) {
247247
/*!
248248
* Absence validator
249249
*/
250-
function validateAbsence(attr, conf, err) {
250+
function validateAbsence(attr, conf, err, options) {
251251
if (!blank(this[attr])) {
252252
err();
253253
}
@@ -256,7 +256,7 @@ function validateAbsence(attr, conf, err) {
256256
/*!
257257
* Length validator
258258
*/
259-
function validateLength(attr, conf, err) {
259+
function validateLength(attr, conf, err, options) {
260260
if (nullCheck.call(this, attr, conf, err)) return;
261261

262262
var len = this[attr].length;
@@ -274,7 +274,7 @@ function validateLength(attr, conf, err) {
274274
/*!
275275
* Numericality validator
276276
*/
277-
function validateNumericality(attr, conf, err) {
277+
function validateNumericality(attr, conf, err, options) {
278278
if (nullCheck.call(this, attr, conf, err)) return;
279279

280280
if (typeof this[attr] !== 'number') {
@@ -288,7 +288,7 @@ function validateNumericality(attr, conf, err) {
288288
/*!
289289
* Inclusion validator
290290
*/
291-
function validateInclusion(attr, conf, err) {
291+
function validateInclusion(attr, conf, err, options) {
292292
if (nullCheck.call(this, attr, conf, err)) return;
293293

294294
if (!~conf.in.indexOf(this[attr])) {
@@ -299,7 +299,7 @@ function validateInclusion(attr, conf, err) {
299299
/*!
300300
* Exclusion validator
301301
*/
302-
function validateExclusion(attr, conf, err) {
302+
function validateExclusion(attr, conf, err, options) {
303303
if (nullCheck.call(this, attr, conf, err)) return;
304304

305305
if (~conf.in.indexOf(this[attr])) {
@@ -310,7 +310,7 @@ function validateExclusion(attr, conf, err) {
310310
/*!
311311
* Format validator
312312
*/
313-
function validateFormat(attr, conf, err) {
313+
function validateFormat(attr, conf, err, options) {
314314
if (nullCheck.call(this, attr, conf, err)) return;
315315

316316
if (typeof this[attr] === 'string') {
@@ -325,14 +325,22 @@ function validateFormat(attr, conf, err) {
325325
/*!
326326
* Custom validator
327327
*/
328-
function validateCustom(attr, conf, err, done) {
328+
function validateCustom(attr, conf, err, options, done) {
329+
if (typeof options === 'function') {
330+
done = options;
331+
options = {};
332+
}
329333
conf.customValidator.call(this, err, done);
330334
}
331335

332336
/*!
333337
* Uniqueness validator
334338
*/
335-
function validateUniqueness(attr, conf, err, done) {
339+
function validateUniqueness(attr, conf, err, options, done) {
340+
if (typeof options === 'function') {
341+
done = options;
342+
options = {};
343+
}
336344
if (blank(this[attr])) {
337345
return process.nextTick(done);
338346
}
@@ -349,7 +357,7 @@ function validateUniqueness(attr, conf, err, done) {
349357

350358
var idName = this.constructor.definition.idName();
351359
var isNewRecord = this.isNewRecord();
352-
this.constructor.find(cond, function(error, found) {
360+
this.constructor.find(cond, options, function(error, found) {
353361
if (error) {
354362
err(error);
355363
} else if (found.length > 1) {
@@ -417,7 +425,8 @@ function getConfigurator(name, opts) {
417425
* @param {Function} callback called with (valid)
418426
* @returns {Boolean} True if no asynchronous validation is configured and all properties pass validation.
419427
*/
420-
Validatable.prototype.isValid = function(callback, data) {
428+
Validatable.prototype.isValid = function(callback, data, options) {
429+
options = options || {};
421430
var valid = true, inst = this, wait = 0, async = false;
422431
var validations = this.constructor.validations;
423432

@@ -456,7 +465,7 @@ Validatable.prototype.isValid = function(callback, data) {
456465
async = true;
457466
wait += 1;
458467
process.nextTick(function() {
459-
validationFailed(inst, attr, v, done);
468+
validationFailed(inst, attr, v, options, done);
460469
});
461470
} else {
462471
if (validationFailed(inst, attr, v)) {
@@ -515,9 +524,14 @@ function cleanErrors(inst) {
515524
});
516525
}
517526

518-
function validationFailed(inst, attr, conf, cb) {
527+
function validationFailed(inst, attr, conf, options, cb) {
519528
var opts = conf.options || {};
520529

530+
if (typeof options === 'function') {
531+
cb = options;
532+
options = {};
533+
}
534+
521535
if (typeof attr !== 'string') return false;
522536

523537
// here we should check skip validation conditions (if, unless)
@@ -558,6 +572,7 @@ function validationFailed(inst, attr, conf, cb) {
558572
if (kind !== false) inst.errors.add(attr, message, code);
559573
fail = true;
560574
});
575+
validatorArguments.push(options);
561576
if (cb) {
562577
validatorArguments.push(function() {
563578
cb(fail);

test/validations.test.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,64 @@ describe('validations', function() {
289289
});
290290
});
291291

292+
describe('validation with or without options', function() {
293+
it('should work on update with options', function(done) {
294+
delete User.validations;
295+
User.validatesPresenceOf('name');
296+
User.create({ name: 'Valid' }, function(e, d) {
297+
d.updateAttribute('name', null, { options: 'options' }, function(e) {
298+
should.exist(e);
299+
e.should.be.instanceOf(Error);
300+
e.should.be.instanceOf(ValidationError);
301+
d.updateAttribute('name', 'Vasiliy', { options: 'options' }, function(e) {
302+
should.not.exist(e);
303+
done();
304+
});
305+
});
306+
});
307+
});
308+
309+
it('should work on update without options', function(done) {
310+
delete User.validations;
311+
User.validatesPresenceOf('name');
312+
User.create({ name: 'Valid' }, function(e, d) {
313+
d.updateAttribute('name', null, function(e) {
314+
should.exist(e);
315+
e.should.be.instanceOf(Error);
316+
e.should.be.instanceOf(ValidationError);
317+
d.updateAttribute('name', 'Vasiliy', function(e) {
318+
should.not.exist(e);
319+
done();
320+
});
321+
});
322+
});
323+
});
324+
325+
it('should work on create with options', function(done) {
326+
delete User.validations;
327+
User.validatesPresenceOf('name');
328+
User.create(function(e, u) {
329+
should.exist(e);
330+
User.create({ name: 'Valid' }, { options: 'options' }, function(e, d) {
331+
should.not.exist(e);
332+
done();
333+
});
334+
});
335+
});
336+
337+
it('should work on create without options', function(done) {
338+
delete User.validations;
339+
User.validatesPresenceOf('name');
340+
User.create(function(e, u) {
341+
should.exist(e);
342+
User.create({ name: 'Valid' }, function(e, d) {
343+
should.not.exist(e);
344+
done();
345+
});
346+
});
347+
});
348+
});
349+
292350
describe('presence', function() {
293351

294352
it('should validate presence', function() {

0 commit comments

Comments
 (0)