diff --git a/lib/model-builder.js b/lib/model-builder.js index eeec2355..9450dcbc 100644 --- a/lib/model-builder.js +++ b/lib/model-builder.js @@ -241,12 +241,18 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett ModelClass.getter = {}; ModelClass.setter = {}; - // Remove properties that reverted by the subclass for (var p in properties) { + // Remove properties that reverted by the subclass if (properties[p] === null || properties[p] === false) { // Hide the base property delete properties[p]; } + + // Warn about properties with unsupported names + if (/\./.test(p)) { + deprecated('Property names containing a dot are not supported. ' + + 'Model: ' + className + ', property: ' + p); + } } var modelDefinition = new ModelDefinition(this, className, properties, settings); diff --git a/lib/model.js b/lib/model.js index 417e9471..85fb01a7 100644 --- a/lib/model.js +++ b/lib/model.js @@ -17,6 +17,7 @@ var _extend = util._extend; var utils = require('./utils'); var fieldsToArray = utils.fieldsToArray; var uuid = require('node-uuid'); +var deprecated = require('depd')('loopback-datasource-juggler'); // Set up an object for quick lookup var BASE_TYPES = { @@ -197,6 +198,13 @@ ModelBaseClass.prototype._initProperties = function (data, options) { if (strict === false || self.__cachedRelations[p]) { self[p] = self.__data[p] = (propVal !== undefined) ? propVal : self.__cachedRelations[p]; + + // Warn about properties with unsupported names + if (/\./.test(p)) { + deprecated('Property names containing a dot are not supported. ' + + 'Model: ' + this.constructor.modelName + + ', dynamic property: ' + p); + } } else if (strict === 'throw') { throw new Error('Unknown property: ' + p); } diff --git a/test/model-definition.test.js b/test/model-definition.test.js index 634e9ba6..588a15ec 100644 --- a/test/model-definition.test.js +++ b/test/model-definition.test.js @@ -10,6 +10,10 @@ var Memory = require('../lib/connectors/memory'); var ModelDefinition = require('../lib/model-definition'); describe('ModelDefinition class', function () { + var memory; + beforeEach(function() { + memory = new DataSource({connector: Memory}); + }); it('should be able to define plain models', function (done) { var modelBuilder = new ModelBuilder(); @@ -253,7 +257,6 @@ describe('ModelDefinition class', function () { }); it('should inherit prototype using option.base', function () { - var memory = new DataSource({connector: Memory}); var modelBuilder = memory.modelBuilder; var parent = memory.createModel('parent', {}, { relations: { @@ -273,7 +276,6 @@ describe('ModelDefinition class', function () { }); it('should ignore inherited options.base', function() { - var memory = new DataSource({connector: Memory}); var modelBuilder = memory.modelBuilder; var base = modelBuilder.define('base'); var child = base.extend('child', {}, { base: 'base' }); @@ -283,7 +285,6 @@ describe('ModelDefinition class', function () { }); it('should ignore inherited options.super', function() { - var memory = new DataSource({connector: Memory}); var modelBuilder = memory.modelBuilder; var base = modelBuilder.define('base'); var child = base.extend('child', {}, { super: 'base' }); @@ -293,7 +294,6 @@ describe('ModelDefinition class', function () { }); it('should serialize protected properties into JSON', function() { - var memory = new DataSource({connector: Memory}); var modelBuilder = memory.modelBuilder; var ProtectedModel = memory.createModel('protected', {}, { protected: ['protectedProperty'] @@ -308,7 +308,6 @@ describe('ModelDefinition class', function () { }); it('should not serialize protected properties of nested models into JSON', function(done){ - var memory = new DataSource({connector: Memory}); var modelBuilder = memory.modelBuilder; var Parent = memory.createModel('parent'); var Child = memory.createModel('child', {}, {protected: ['protectedProperty']}); @@ -332,7 +331,6 @@ describe('ModelDefinition class', function () { }); it('should not serialize hidden properties into JSON', function () { - var memory = new DataSource({connector: Memory}); var modelBuilder = memory.modelBuilder; var HiddenModel = memory.createModel('hidden', {}, { hidden: ['secret'] @@ -350,7 +348,6 @@ describe('ModelDefinition class', function () { }); it('should not serialize hidden properties of nested models into JSON', function (done) { - var memory = new DataSource({connector: Memory}); var modelBuilder = memory.modelBuilder; var Parent = memory.createModel('parent'); var Child = memory.createModel('child', {}, {hidden: ['secret']}); @@ -372,5 +369,26 @@ describe('ModelDefinition class', function () { }); }); }); + + it('should report deprecation warning for property names containing dot', function() { + var message = 'deprecation not reported'; + process.once('deprecation', function(err) { message = err.message; }); + + memory.createModel('Dotted', { 'dot.name': String }); + + message.should.match(/Dotted.*dot\.name/); + }); + + it('should report deprecation warning for dynamic property names containing dot', function(done) { + var message = 'deprecation not reported'; + process.once('deprecation', function(err) { message = err.message; }); + + var Model = memory.createModel('DynamicDotted'); + Model.create({ 'dot.name': 'dot.value' }, function(err) { + if (err) return done(err); + message.should.match(/Dotted.*dot\.name/); + done(); + }); + }); });