diff --git a/lib/datasource.js b/lib/datasource.js index be663cbf..254fca15 100644 --- a/lib/datasource.js +++ b/lib/datasource.js @@ -398,12 +398,6 @@ DataSource.prototype.defineRelations = function(modelClass, relations) { * @param settings */ DataSource.prototype.setupDataAccess = function (modelClass, settings) { -// add data access objects - this.mixin(modelClass); - - var relations = settings.relationships || settings.relations; - this.defineRelations(modelClass, relations); - if (this.connector && this.connector.define) { // pass control to connector this.connector.define({ @@ -412,6 +406,13 @@ DataSource.prototype.setupDataAccess = function (modelClass, settings) { settings: settings }); } + + // add data access objects + this.mixin(modelClass); + + var relations = settings.relationships || settings.relations; + this.defineRelations(modelClass, relations); + }; /** diff --git a/lib/model-builder.js b/lib/model-builder.js index 9a935702..a0914db5 100644 --- a/lib/model-builder.js +++ b/lib/model-builder.js @@ -5,6 +5,7 @@ var inflection = require('inflection'); var EventEmitter = require('events').EventEmitter; var util = require('util'); +var assert = require('assert'); var DefaultModelBaseClass = require('./model.js'); var List = require('./list.js'); var ModelDefinition = require('./model-definition.js'); @@ -47,6 +48,13 @@ util.inherits(ModelBuilder, EventEmitter); // Create a default instance ModelBuilder.defaultInstance = new ModelBuilder(); +function isModelClass(cls) { + if(!cls) { + return false; + } + return cls.prototype instanceof DefaultModelBaseClass; +} + /** * Define a model class * @@ -82,7 +90,6 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett var dataSource = this; var args = slice.call(arguments); var pluralName = settings && settings.plural; - var ModelBaseClass = parent || DefaultModelBaseClass; if (!className) { throw new Error('Class name required'); @@ -104,6 +111,18 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett settings.strict = false; } + // Set up the base model class + var ModelBaseClass = parent || DefaultModelBaseClass; + var baseClass = settings.base || settings['super']; + if(baseClass) { + if(isModelClass(baseClass)) { + ModelBaseClass = baseClass; + } else { + ModelBaseClass = this.models[baseClass]; + assert(ModelBaseClass, 'Base model is not found: ' + baseClass); + } + } + // Check if there is a unresolved model with the same name var ModelClass = this.models[className]; diff --git a/test/loopback-dl.test.js b/test/loopback-dl.test.js index 1537132d..9a3e8bc7 100644 --- a/test/loopback-dl.test.js +++ b/test/loopback-dl.test.js @@ -418,6 +418,31 @@ describe('DataSource define model', function () { }); +describe('Load models with base', function () { + it('should set up base class', function (done) { + var ds = new ModelBuilder(); + + var User = ds.define('User', {name: String}); + + User.staticMethod = function staticMethod() {}; + User.prototype.instanceMethod = function instanceMethod() {}; + + var Customer = ds.define('Customer', {vip: Boolean}, {base: 'User'}); + + assert(Customer.prototype instanceof User); + assert(Customer.staticMethod === User.staticMethod); + assert(Customer.prototype.instanceMethod === User.prototype.instanceMethod); + + + try { + var Customer1 = ds.define('Customer1', {vip: Boolean}, {base: 'User1'}); + } catch(e) { + assert(e); + } + + done(); + }); +}); describe('Load models with relations', function () { it('should set up relations', function (done) {