From cf200a2e277c0eed95e435a35bc47a3d55ef4b0c Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Fri, 24 Jan 2014 14:51:01 -0800 Subject: [PATCH 1/2] Add getType/getDefaultIdType from connectors --- lib/connector.js | 16 ++++++++++++++++ lib/connectors/memory.js | 8 ++++++++ lib/datasource.js | 36 +++++++++++++++++++++++++++--------- lib/sql.js | 16 ++++++++++++++++ test/loopback-dl.test.js | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 101 insertions(+), 9 deletions(-) diff --git a/lib/connector.js b/lib/connector.js index efb3843d..9372ef6d 100644 --- a/lib/connector.js +++ b/lib/connector.js @@ -17,6 +17,22 @@ function Connector(name, settings) { */ Connector.prototype.relational = false; +/*! + * Get the connector type/subtype + * @returns {String} The type for the connector + */ +Connector.prototype.getType = function() { + return 'db/nosql'; +}; + +/** + * Get the default data type for ID + * @returns {Function} The default type for ID + */ +Connector.prototype.getDefaultIdType = function() { + return String; +}; + /** * Execute a command with given parameters * @param {String} command The command such as SQL diff --git a/lib/connectors/memory.js b/lib/connectors/memory.js index 7c337d43..29e6dd8e 100644 --- a/lib/connectors/memory.js +++ b/lib/connectors/memory.js @@ -35,6 +35,14 @@ function Memory(m, settings) { util.inherits(Memory, Connector); +Memory.prototype.getDefaultIdType = function() { + return Number; +}; + +Memory.prototype.getType = function() { + return 'db/nosql/memory'; +}; + Memory.prototype.connect = function (callback) { if (this.isTransaction) { this.onTransactionExec = callback; diff --git a/lib/datasource.js b/lib/datasource.js index 8f11368c..c035b23b 100644 --- a/lib/datasource.js +++ b/lib/datasource.js @@ -424,17 +424,27 @@ DataSource.prototype.defineRelations = function (modelClass, relations) { /*! * Set up the data access functions from the data source - * @param modelClass - * @param settings + * @param {Model} modelClass The model class + * @param {Object} settings The settings object */ DataSource.prototype.setupDataAccess = function (modelClass, settings) { - if (this.connector && this.connector.define) { - // pass control to connector - this.connector.define({ - model: modelClass, - properties: modelClass.definition.properties, - settings: settings - }); + if (this.connector) { + // Check if the id property should be generated + var idName = modelClass.definition.idName(); + var idProp = modelClass.definition.properties[idName]; + if(idProp && idProp.generated && this.connector.getDefaultIdType) { + // Set the default id type from connector's ability + var idType = this.connector.getDefaultIdType() || String; + idProp.type = idType; + } + if (this.connector.define) { + // pass control to connector + this.connector.define({ + model: modelClass, + properties: modelClass.definition.properties, + settings: settings + }); + } } // add data access objects @@ -567,6 +577,14 @@ DataSource.prototype.getModelDefinition = function (name) { return this.modelBuilder.getModelDefinition(name); }; +/** + * Get the data source type + * @returns {String} The data source type, such as db/relational, db/nosql, rest + */ +DataSource.prototype.getType = function() { + return this.connector && this.connector.getType(); +}; + /** * Attach an existing model to a data source. * diff --git a/lib/sql.js b/lib/sql.js index b3b5c664..06e33dc5 100644 --- a/lib/sql.js +++ b/lib/sql.js @@ -19,6 +19,22 @@ util.inherits(BaseSQL, Connector); */ BaseSQL.prototype.relational = true; +/*! + * Get the connector type/subtype + * @returns {string} + */ +BaseSQL.prototype.getType = function() { + return 'db/relational'; +}; + +/*! + * Get the default data type for ID + * @returns {Function} + */ +BaseSQL.prototype.getDefaultIdType = function() { + return Number; +}; + BaseSQL.prototype.query = function () { throw new Error('query method should be declared in connector'); }; diff --git a/test/loopback-dl.test.js b/test/loopback-dl.test.js index 205ee4e1..49ac88ab 100644 --- a/test/loopback-dl.test.js +++ b/test/loopback-dl.test.js @@ -416,6 +416,40 @@ describe('DataSource define model', function () { }); }); + it('injects id by default', function (done) { + var ds = new ModelBuilder(); + + var User = ds.define('User', {}); + assert.deepEqual(User.definition.properties.id, + {type: Number, id: 1, generated: true}); + + done(); + }); + + it('disables idInjection if the value is false', function (done) { + var ds = new ModelBuilder(); + + var User1 = ds.define('User', {}, {idInjection: false}); + assert(!User1.definition.properties.id); + done(); + }); + + it('updates generated id type by the connector', function (done) { + var builder = new ModelBuilder(); + + var User = builder.define('User', {id: {type: String, generated: true, id: true}}); + assert.deepEqual(User.definition.properties.id, + {type: String, id: 1, generated: true}); + + var ds = new DataSource('memory');// define models + User.attachTo(ds); + + assert.deepEqual(User.definition.properties.id, + {type: Number, id: 1, generated: true}); + + done(); + }); + }); describe('Load models with base', function () { From da571c0c231c09f4dc5405b6bedb482d6150de17 Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Tue, 28 Jan 2014 14:23:48 -0800 Subject: [PATCH 2/2] Use String[] for types and add test for supported types --- lib/connector.js | 30 ++++++++++++++++++++++++----- lib/connectors/memory.js | 4 ++-- lib/datasource.js | 41 ++++++++++++++++++++++++++++++++++++---- lib/model-builder.js | 5 +++++ lib/sql.js | 10 +++++----- test/loopback-dl.test.js | 36 +++++++++++++++++++++++++++++++++++ 6 files changed, 110 insertions(+), 16 deletions(-) diff --git a/lib/connector.js b/lib/connector.js index 9372ef6d..86f0998c 100644 --- a/lib/connector.js +++ b/lib/connector.js @@ -17,12 +17,12 @@ function Connector(name, settings) { */ Connector.prototype.relational = false; -/*! - * Get the connector type/subtype - * @returns {String} The type for the connector +/** + * Get types associated with the connector + * @returns {String[]} The types for the connector */ -Connector.prototype.getType = function() { - return 'db/nosql'; +Connector.prototype.getTypes = function() { + return ['db', 'nosql']; }; /** @@ -33,6 +33,26 @@ Connector.prototype.getDefaultIdType = function() { return String; }; +/** + * Get the metadata for the connector + * @returns {Object} The metadata object + * @property {String} type The type for the backend + * @property {Function} defaultIdType The default id type + * @property {Boolean} [isRelational] If the connector represents a relational database + * @property {Object} schemaForSettings The schema for settings object + */ +Connector.prototype.getMedadata = function () { + if (!this._metadata) { + this._metadata = { + types: this.getTypes(), + defaultIdType: this.getDefaultIdType(), + isRelational: this.isRelational || (this.getTypes().indexOf('rdbms') !== -1), + schemaForSettings: {} + }; + } + return this._metadata; +}; + /** * Execute a command with given parameters * @param {String} command The command such as SQL diff --git a/lib/connectors/memory.js b/lib/connectors/memory.js index 29e6dd8e..1184ac44 100644 --- a/lib/connectors/memory.js +++ b/lib/connectors/memory.js @@ -39,8 +39,8 @@ Memory.prototype.getDefaultIdType = function() { return Number; }; -Memory.prototype.getType = function() { - return 'db/nosql/memory'; +Memory.prototype.getTypes = function() { + return ['db', 'nosql', 'memory']; }; Memory.prototype.connect = function (callback) { diff --git a/lib/datasource.js b/lib/datasource.js index c035b23b..9ced62d8 100644 --- a/lib/datasource.js +++ b/lib/datasource.js @@ -569,20 +569,53 @@ DataSource.prototype.mixin = function (ModelCtor) { }); }; +/** + * @see ModelBuilder.prototype.getModel + */ DataSource.prototype.getModel = function (name, forceCreate) { return this.modelBuilder.getModel(name, forceCreate); }; +/** + * @see ModelBuilder.prototype.getModelDefinition + */ DataSource.prototype.getModelDefinition = function (name) { return this.modelBuilder.getModelDefinition(name); }; /** - * Get the data source type - * @returns {String} The data source type, such as db/relational, db/nosql, rest + * Get the data source types + * @returns {String[]} The data source type, such as ['db', 'nosql', 'mongodb'], + * ['rest'], or ['db', 'rdbms', 'mysql'] */ -DataSource.prototype.getType = function() { - return this.connector && this.connector.getType(); +DataSource.prototype.getTypes = function () { + var types = this.connector && this.connector.getTypes() || []; + if (typeof types === 'string') { + types = types.split(/[\s,\/]+/); + } + return types; +}; + +/** + * Check the data source supports the given types + * @param String|String[]) types A type name or an array of type names + * @return {Boolean} true if all types are supported by the data source + */ +DataSource.prototype.supportTypes = function (types) { + var supportedTypes = this.getTypes(); + if (Array.isArray(types)) { + // Check each of the types + for (var i = 0; i < types.length; i++) { + if (supportedTypes.indexOf(types[i]) === -1) { + // Not supported + return false; + } + } + return true; + } else { + // The types is a string + return supportedTypes.indexOf(types) !== -1; + } }; /** diff --git a/lib/model-builder.js b/lib/model-builder.js index ab8aa1b2..03bbcc91 100644 --- a/lib/model-builder.js +++ b/lib/model-builder.js @@ -71,6 +71,11 @@ ModelBuilder.prototype.getModel = function (name, forceCreate) { return model; }; +/** + * Get the model definition by name + * @param {String} name The model name + * @returns {ModelDefinition} The model definition + */ ModelBuilder.prototype.getModelDefinition = function (name) { return this.definitions[name]; }; diff --git a/lib/sql.js b/lib/sql.js index 06e33dc5..3f32882b 100644 --- a/lib/sql.js +++ b/lib/sql.js @@ -19,12 +19,12 @@ util.inherits(BaseSQL, Connector); */ BaseSQL.prototype.relational = true; -/*! - * Get the connector type/subtype - * @returns {string} +/** + * Get types associated with the connector + * @returns {String[]} The types for the connector */ -BaseSQL.prototype.getType = function() { - return 'db/relational'; + BaseSQL.prototype.getTypes = function() { + return ['db', 'rdbms', 'sql']; }; /*! diff --git a/test/loopback-dl.test.js b/test/loopback-dl.test.js index 49ac88ab..0f49514f 100644 --- a/test/loopback-dl.test.js +++ b/test/loopback-dl.test.js @@ -479,6 +479,42 @@ describe('Load models with base', function () { }); }); +describe('DataSource connector types', function() { + it('should return an array of types', function() { + var ds = new DataSource('memory'); + var types = ds.getTypes(); + assert.deepEqual(types, ['db', 'nosql', 'memory']); + }); + + it('should test supported types by string', function() { + var ds = new DataSource('memory'); + var result = ds.supportTypes('db'); + assert(result); + }); + + it('should test supported types by array', function() { + var ds = new DataSource('memory'); + var result = ds.supportTypes(['db', 'memory']); + assert(result); + }); + + it('should test unsupported types by string', function() { + var ds = new DataSource('memory'); + var result = ds.supportTypes('rdbms'); + assert(!result); + }); + + it('should test unsupported types by array', function() { + var ds = new DataSource('memory'); + var result = ds.supportTypes(['rdbms', 'memory']); + assert(!result); + + result = ds.supportTypes(['rdbms']); + assert(!result); + }); + +}); + describe('DataSource constructor', function () { // Mocked require var loader = function (name) {