diff --git a/Readme.md b/Readme.md index 0e6b1c19..6a3e2a5b 100755 --- a/Readme.md +++ b/Readme.md @@ -736,6 +736,12 @@ You can mark the `owner_id` field as required in the database by specifying the Animal.hasOne("owner", Person, { required: true }); ``` +If a field is not required, but should be validated even if it is not present, then specify the `alwaysValidate` option. +(this can happen, for example when validation of a null field depends on other fields in the record) +```js +Animal.hasOne("owner", Person, { required: false, alwaysValidate: true }); +``` + If you prefer to use another name for the field (owner_id) you can change this parameter in the settings. ```js diff --git a/lib/Instance.js b/lib/Instance.js index 609c4cd5..beefce89 100755 --- a/lib/Instance.js +++ b/lib/Instance.js @@ -54,6 +54,7 @@ function Instance(Model, opts) { if (Model.allProperties[k]) { required = Model.allProperties[k].required; + alwaysValidate = Model.allProperties[k].alwaysValidate; } else { for (i = 0; i < opts.one_associations.length; i++) { if (opts.one_associations[i].field === k) { @@ -62,8 +63,7 @@ function Instance(Model, opts) { } } } - - if (!required && instance[k] == null) { + if (!alwaysValidate && !required && instance[k] == null) { continue; // avoid validating if property is not required and is "empty" } for (i = 0; i < opts.validations[k].length; i++) { diff --git a/test/integration/validation.js b/test/integration/validation.js index 8482f0f7..8e5edb18 100644 --- a/test/integration/validation.js +++ b/test/integration/validation.js @@ -9,6 +9,7 @@ var ORM = require('../../'); describe("Validations", function() { var db = null; var Person = null; + var Person2 = null; var setup = function (returnAll, required) { return function (done) { @@ -17,7 +18,7 @@ describe("Validations", function() { Person = db.define("person", { name: { type: 'text' }, - height: { type: 'number' } + height: { type: 'number' }, }, { validations: { name: ORM.validators.rangeLength(3, 30), @@ -29,6 +30,29 @@ describe("Validations", function() { }; }; + notNull = function(val, next, data) { + if (val != null) { + return next('notnull'); + } + return next(); + }; + var setupAlwaysValidate = function () { + return function (done) { + Person2 = db.define("person2", { + name: { type: 'text' }, + mustbenull: { type: 'text', required:false, alwaysValidate: true } + , canbenull: { type: 'text', required:false } + }, { + validations: { + name: ORM.validators.rangeLength(3, 30), + mustbenull: notNull, + canbenull: notNull + } + }); + return helper.dropSync(Person2, done); + }; + }; + before(function (done) { helper.connect(function (connection) { db = connection; @@ -40,6 +64,32 @@ describe("Validations", function() { db.close(); }); + + describe("alwaysValidate", function () { + before(setupAlwaysValidate()); + + it("I want to see it fail first (the absence of evidence)", function(done) { + var rachel = new Person2({name: 'rachel', canbenull:null, mustbenull:null}); + rachel.save(function (err) { + should.not.exist(err); + return done(); + }); + }); + + it("then it should work", function(done) { + var tom = new Person2({name: 'tom', canbenull:null, mustbenull:'notnull'}); + tom.save(function (err) { + should.exist(err); + should.equal(typeof err, "object"); + should.equal(err.property, "mustbenull"); + should.equal(err.msg, "notnull"); + should.equal(err.type, "validation"); + should.equal(tom.id, null); + return done(); + }); + }); + }); + describe("predefined", function () { before(setup(false, false)); @@ -59,7 +109,7 @@ describe("Validations", function() { }); describe("unique", function () { - if (protocol === "mongodb") return; + if (protocol === "mongodb") return; var Product = null; @@ -77,8 +127,6 @@ describe("Validations", function() { productId : ORM.validators.unique() // this must be straight after a required & validated row. } }); - Product.hasOne('product', Product, { field: 'productId', required: false, autoFetch: true }); - return helper.dropSync(Product, done); }; }; @@ -220,6 +268,7 @@ describe("Validations", function() { }); }); }); + }); }); }); @@ -363,4 +412,7 @@ describe("Validations", function() { }); }); }); + + }); +