From 39907c6421d5dafe0cf7a1528e103334a7412308 Mon Sep 17 00:00:00 2001 From: Dimitris Halatsis Date: Sat, 28 May 2016 01:21:53 +0300 Subject: [PATCH] ModelBuilder: add new setting strictEmbeddedModels The setting controls the strict mode used for embedded property types, for example the type of "address" property in this model definition: modelBuilder.define('TestEmbedded', { name: 'string', address: { street: 'string', }, }); [back-port of #955] --- lib/model-builder.js | 7 +++- test/loopback-dl.test.js | 79 ++++++++++++++++++++++++++++++++++++++++ test/relations.test.js | 6 ++- 3 files changed, 89 insertions(+), 3 deletions(-) diff --git a/lib/model-builder.js b/lib/model-builder.js index 50b09f30..3be47b66 100644 --- a/lib/model-builder.js +++ b/lib/model-builder.js @@ -44,6 +44,7 @@ function ModelBuilder() { // create blank models pool this.models = {}; this.definitions = {}; + this.settings = {}; this.mixins = new MixinProvider(this); this.defaultModelBaseClass = DefaultModelBaseClass; } @@ -703,7 +704,11 @@ ModelBuilder.prototype.resolveType = function(type) { return this.resolveType(type.type); } else { return this.define(this.getSchemaName(null), - type, { anonymous: true, idInjection: false }); + type, { + anonymous: true, + idInjection: false, + strict: this.settings.strictEmbeddedModels || false, + }); } } else if ('function' === typeof type) { return type; diff --git a/test/loopback-dl.test.js b/test/loopback-dl.test.js index 824115a2..74d31a66 100644 --- a/test/loopback-dl.test.js +++ b/test/loopback-dl.test.js @@ -1902,4 +1902,83 @@ describe('ModelBuilder options.models', function() { var M1 = builder.define('M1'); assert.equal(M2.M1, M1, 'M1 should be injected to M2'); }); + + it('should use false strict mode for embedded models by default', function() { + var builder = new ModelBuilder(); + var M1 = builder.define('testEmbedded', { + name: 'string', + address: { + street: 'string', + }, + }); + var m1 = new M1({ + name: 'Jim', + address: { + street: 'washington st', + number: 5512, + }, + }); + assert.equal(m1.address.number, 5512, 'm1 should contain number property in address'); + }); + + it('should use the strictEmbeddedModels setting (true) when applied on modelBuilder', function() { + var builder = new ModelBuilder(); + builder.settings.strictEmbeddedModels = true; + var M1 = builder.define('testEmbedded', { + name: 'string', + address: { + street: 'string', + }, + }); + var m1 = new M1({ + name: 'Jim', + address: { + street: 'washington st', + number: 5512, + }, + }); + assert.equal(m1.address.number, undefined, 'm1 should not contain number property in address'); + }); + + it('should use strictEmbeddedModels setting (validate) when applied on modelBuilder', function() { + var builder = new ModelBuilder(); + builder.settings.strictEmbeddedModels = 'validate'; + var M1 = builder.define('testEmbedded', { + name: 'string', + address: { + street: 'string', + }, + }); + var m1 = new M1({ + name: 'Jim', + address: { + street: 'washington st', + number: 5512, + }, + }); + assert.equal(m1.address.number, undefined, 'm1 should not contain number property in address'); + assert.equal(m1.address.isValid(), false, 'm1 address should not validate with extra property'); + var codes = m1.address.errors && m1.address.errors.codes || {}; + assert.deepEqual(codes.number, ['unknown-property']); + }); + + it('should use the strictEmbeddedModels setting (throw) when applied on modelBuilder', function() { + var builder = new ModelBuilder(); + builder.settings.strictEmbeddedModels = 'throw'; + var M1 = builder.define('testEmbedded', { + name: 'string', + address: { + street: 'string', + }, + }); + assert.throws(function() { + var m1 = new M1({ + name: 'Jim', + address: { + street: 'washington st', + number: 5512, + }, + }); + }); + }); }); diff --git a/test/relations.test.js b/test/relations.test.js index a383637a..63c4d4c5 100644 --- a/test/relations.test.js +++ b/test/relations.test.js @@ -3837,8 +3837,10 @@ describe('relations', function() { // db = getSchema(); Person = db.define('Person', { name: String }); Passport = tmp.define('Passport', - { id: { type: 'string', id: true, generated: true }}, - { name: { type: 'string', required: true }} + { + id: { type: 'string', id: true, generated: true }, + name: { type: 'string', required: true }, + } ); });