Add models to LDL options

1. Use 'models' to specify the dependencies to other models
2. The 'models' property is an object, such as:

{
    Model1: 'Model1',
    Model2: Model2
}

3. The model classes will be injected into the newly defined class as
static properties using the keys from the models option.
This commit is contained in:
Raymond Feng 2013-12-18 16:13:41 -08:00
parent 7d19b94c97
commit e1ec152c78
3 changed files with 61 additions and 14 deletions

View File

@ -363,18 +363,10 @@ DataSource.prototype.defineRelations = function(modelClass, relations) {
for (var rn in relations) {
var r = relations[rn];
assert(DataSource.relationTypes.indexOf(r.type) !== -1, "Invalid relation type: " + r.type);
var targetModel = isModelClass(r.model) ? r.model : this.getModel(r.model);
if (!targetModel) {
// The target model doesn't exist, let create a place holder for it
targetModel = this.define(r.model, {}, {unresolved: true});
}
var targetModel = isModelClass(r.model) ? r.model : this.getModel(r.model, true);
var throughModel = null;
if (r.through) {
throughModel = isModelClass(r.through) ? r.through : this.getModel(r.through);
if (!throughModel) {
// The through model doesn't exist, let create a place holder for it
throughModel = this.define(r.through, {}, {unresolved: true});
}
throughModel = isModelClass(r.through) ? r.through : this.getModel(r.through, true);
}
if (!isModelDataSourceAttached(targetModel) || (throughModel && !isModelDataSourceAttached(throughModel))) {
// Create a listener to defer the relation set up
@ -533,8 +525,8 @@ DataSource.prototype.mixin = function (ModelCtor) {
});
};
DataSource.prototype.getModel = function(name) {
return this.modelBuilder.getModel(name);
DataSource.prototype.getModel = function(name, forceCreate) {
return this.modelBuilder.getModel(name, forceCreate);
};
DataSource.prototype.getModelDefinition = function(name) {

View File

@ -56,8 +56,19 @@ function isModelClass(cls) {
return cls.prototype instanceof DefaultModelBaseClass;
}
ModelBuilder.prototype.getModel = function(name) {
return this.models[name];
/**
* Get a model by name
* @param {String} name The model name
* @param {Boolean} forceCreate Indicate if a stub should be created for the
* given name if a model doesn't exist
* @returns {*} The model class
*/
ModelBuilder.prototype.getModel = function(name, forceCreate) {
var model = this.models[name];
if(!model && forceCreate) {
model = this.define(name, {}, {unresolved: true});
}
return model;
};
ModelBuilder.prototype.getModelDefinition = function(name) {
@ -185,6 +196,14 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
ModelClass[i] = ModelBaseClass[i];
}
}
// Load and inject the model classes
if(settings.models) {
Object.keys(settings.models).forEach(function(m) {
var model = settings.models[m];
ModelClass[m] = typeof model === 'string' ? modelBuilder.getModel(model, true) : model;
});
}
ModelClass.getter = {};
ModelClass.setter = {};

View File

@ -906,3 +906,39 @@ describe('Injected methods from connectors', function(){
});
});
describe('ModelBuilder options.models', function(){
it('should inject model classes from models', function() {
var builder = new ModelBuilder();
var M1 = builder.define('M1');
var M2 = builder.define('M2', {}, {models: {
'M1': M1
}});
assert.equal(M2.M1, M1, 'M1 should be injected to M2');
});
it('should inject model classes by name in the models', function() {
var builder = new ModelBuilder();
var M1 = builder.define('M1');
var M2 = builder.define('M2', {}, {models: {
'M1': 'M1'
}});
assert.equal(M2.M1, M1, 'M1 should be injected to M2');
});
it('should inject model classes by name in the models before the class is defined',
function() {
var builder = new ModelBuilder();
var M2 = builder.define('M2', {}, {models: {
'M1': 'M1'
}});
assert(M2.M1, 'M1 should be injected to M2');
assert(M2.M1.settings.unresolved, 'M1 is still a proxy');
var M1 = builder.define('M1');
assert.equal(M2.M1, M1, 'M1 should be injected to M2');
});
});