Add new strict mode "validate"
When a model is configured with `strict: 'validate'`, any dynamic properties not included in the schema trigger a validation error.
This commit is contained in:
parent
2bdcce0d96
commit
99d4c6aa8d
18
lib/model.js
18
lib/model.js
|
@ -120,14 +120,26 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
|
|||
enumerable: false,
|
||||
configurable: true,
|
||||
value: false
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
if (strict === 'validate') {
|
||||
Object.defineProperty(this, '__unknownProperties', {
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configrable: true,
|
||||
value: []
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.__cachedRelations = {};
|
||||
this.__data = {};
|
||||
this.__dataSource = options.dataSource;
|
||||
this.__strict = strict;
|
||||
this.__persisted = false;
|
||||
if (strict === 'validate') {
|
||||
this.__unknownProperties = [];
|
||||
}
|
||||
}
|
||||
|
||||
if (options.persisted !== undefined) {
|
||||
|
@ -207,6 +219,8 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
|
|||
}
|
||||
} else if (strict === 'throw') {
|
||||
throw new Error('Unknown property: ' + p);
|
||||
} else if (strict === 'validate') {
|
||||
this.__unknownProperties.push(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -616,7 +630,7 @@ ModelBaseClass.observe = function(operation, listener) {
|
|||
*/
|
||||
ModelBaseClass.removeObserver = function(operation, listener) {
|
||||
if (!this._observers[operation]) return;
|
||||
|
||||
|
||||
var index = this._observers[operation].indexOf(listener);
|
||||
if (index != -1) this._observers[operation].splice(index, 1);
|
||||
};
|
||||
|
|
|
@ -411,8 +411,11 @@ Validatable.prototype.isValid = function (callback, data) {
|
|||
var valid = true, inst = this, wait = 0, async = false;
|
||||
var validations = this.constructor.validations;
|
||||
|
||||
var reportDiscardedProperties = this.__strict === 'validate' &&
|
||||
this.__unknownProperties && this.__unknownProperties.length;
|
||||
|
||||
// exit with success when no errors
|
||||
if (typeof validations !== 'object') {
|
||||
if (typeof validations !== 'object' && !reportDiscardedProperties) {
|
||||
cleanErrors(this);
|
||||
if (callback) {
|
||||
this.trigger('validate', function (validationsDone) {
|
||||
|
@ -453,6 +456,16 @@ Validatable.prototype.isValid = function (callback, data) {
|
|||
});
|
||||
});
|
||||
|
||||
if (reportDiscardedProperties) {
|
||||
for (var ix in inst.__unknownProperties) {
|
||||
var key = inst.__unknownProperties[ix];
|
||||
var code = 'unknown-property';
|
||||
var msg = defaultMessages[code];
|
||||
inst.errors.add(key, msg, code);
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!async) {
|
||||
validationsDone.call(inst, function () {
|
||||
if (valid) cleanErrors(inst);
|
||||
|
@ -568,6 +581,7 @@ function skipValidation(inst, conf, kind) {
|
|||
var defaultMessages = {
|
||||
presence: 'can\'t be blank',
|
||||
absence: 'can\'t be set',
|
||||
'unknown-property': 'is not defined in the model',
|
||||
length: {
|
||||
min: 'too short',
|
||||
max: 'too long',
|
||||
|
|
|
@ -456,6 +456,17 @@ describe('DataSource define model', function () {
|
|||
done(null, User);
|
||||
});
|
||||
|
||||
describe('strict mode "validate"', function() {
|
||||
it('should report validation error for unknown properties', function() {
|
||||
var ds = new DataSource('memory');
|
||||
var User = ds.define('User', { name: String }, { strict: 'validate' });
|
||||
var user = new User({ name: 'Joe', age: 20 });
|
||||
user.isValid().should.be.false;
|
||||
var codes = user.errors && user.errors.codes || {};
|
||||
codes.should.have.property('age').eql(['unknown-property']);
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to define open models', function (done) {
|
||||
var ds = new DataSource('memory');
|
||||
|
||||
|
|
Loading…
Reference in New Issue