Merge branch 'release/2.2.1' into production
This commit is contained in:
commit
5a4d78ffc8
|
@ -393,7 +393,7 @@ DataSource.prototype.defineRelations = function (modelClass, relations) {
|
|||
// Create a function for the closure in the loop
|
||||
var createListener = function (name, relation, targetModel, throughModel) {
|
||||
if (!isModelDataSourceAttached(targetModel)) {
|
||||
targetModel.once('dataSourceAttached', function (model) {
|
||||
targetModel.once('dataAccessConfigured', function (model) {
|
||||
// Check if the through model doesn't exist or resolved
|
||||
if (!throughModel || isModelDataSourceAttached(throughModel)) {
|
||||
// The target model is resolved
|
||||
|
@ -410,7 +410,7 @@ DataSource.prototype.defineRelations = function (modelClass, relations) {
|
|||
}
|
||||
if (throughModel && !isModelDataSourceAttached(throughModel)) {
|
||||
// Set up a listener to the through model
|
||||
throughModel.once('dataSourceAttached', function (model) {
|
||||
throughModel.once('dataAccessConfigured', function (model) {
|
||||
if (isModelDataSourceAttached(targetModel)) {
|
||||
// The target model is resolved
|
||||
var params = traverse(relations).clone();
|
||||
|
@ -479,9 +479,15 @@ DataSource.prototype.setupDataAccess = function (modelClass, settings) {
|
|||
// add data access objects
|
||||
this.mixin(modelClass);
|
||||
|
||||
// define relations from LDL (options.relations)
|
||||
var relations = settings.relationships || settings.relations;
|
||||
this.defineRelations(modelClass, relations);
|
||||
|
||||
// Emit the dataAccessConfigured event to indicate all the methods for data
|
||||
// access have been mixed into the model class
|
||||
modelClass.emit('dataAccessConfigured', modelClass);
|
||||
|
||||
// define scopes from LDL (options.relations)
|
||||
var scopes = settings.scopes || {};
|
||||
this.defineScopes(modelClass, scopes);
|
||||
|
||||
|
|
|
@ -110,7 +110,10 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
|
|||
var args = slice.call(arguments);
|
||||
var pluralName = (settings && settings.plural) ||
|
||||
inflection.pluralize(className);
|
||||
|
||||
|
||||
var httpOptions = (settings && settings.http) || {};
|
||||
var pathName = httpOptions.path || pluralName;
|
||||
|
||||
if (!className) {
|
||||
throw new Error('Class name required');
|
||||
}
|
||||
|
@ -188,7 +191,7 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
|
|||
hiddenProperty(ModelClass, 'dataSource', modelBuilder); // Keep for back-compatibility
|
||||
hiddenProperty(ModelClass, 'pluralModelName', pluralName);
|
||||
hiddenProperty(ModelClass, 'relations', {});
|
||||
hiddenProperty(ModelClass, 'http', { path: '/' + pluralName });
|
||||
hiddenProperty(ModelClass, 'http', { path: '/' + pathName });
|
||||
hiddenProperty(ModelClass, 'base', ModelBaseClass);
|
||||
|
||||
// inherit ModelBaseClass static methods
|
||||
|
|
|
@ -70,11 +70,7 @@ function extendScopeMethods(definition, scopeMethods, ext) {
|
|||
return relationMethod.apply(relation, arguments);
|
||||
};
|
||||
if (relationMethod.shared) {
|
||||
method.shared = true;
|
||||
method.accepts = relationMethod.accepts;
|
||||
method.returns = relationMethod.returns;
|
||||
method.http = relationMethod.http;
|
||||
method.description = relationMethod.description;
|
||||
sharedMethod(definition, key, method, relationMethod);
|
||||
}
|
||||
customMethods.push(key);
|
||||
}
|
||||
|
@ -573,15 +569,19 @@ function scopeMethod(definition, methodName) {
|
|||
|
||||
var relationMethod = relationClass.prototype[methodName];
|
||||
if (relationMethod.shared) {
|
||||
method.shared = true;
|
||||
method.accepts = relationMethod.accepts;
|
||||
method.returns = relationMethod.returns;
|
||||
method.http = relationMethod.http;
|
||||
method.description = relationMethod.description;
|
||||
sharedMethod(definition, methodName, method, relationMethod);
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
function sharedMethod(definition, methodName, method, relationMethod) {
|
||||
method.shared = true;
|
||||
method.accepts = relationMethod.accepts;
|
||||
method.returns = relationMethod.returns;
|
||||
method.http = relationMethod.http;
|
||||
method.description = relationMethod.description;
|
||||
};
|
||||
|
||||
/**
|
||||
* Find a related item by foreign key
|
||||
* @param {*} fkId The foreign key
|
||||
|
@ -1295,6 +1295,15 @@ RelationDefinition.hasOne = function (modelFrom, modelTo, params) {
|
|||
return relationMethod;
|
||||
}
|
||||
});
|
||||
|
||||
// FIXME: [rfeng] Wrap the property into a function for remoting
|
||||
// so that it can be accessed as /api/<model>/<id>/<hasOneRelationName>
|
||||
// For example, /api/orders/1/customer
|
||||
var fn = function() {
|
||||
var f = this[relationName];
|
||||
f.apply(this, arguments);
|
||||
};
|
||||
modelFrom.prototype['__get__' + relationName] = fn;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
10
lib/scope.js
10
lib/scope.js
|
@ -248,9 +248,15 @@ function mergeQuery(base, update) {
|
|||
}
|
||||
}
|
||||
|
||||
// Overwrite inclusion
|
||||
// Merge inclusion
|
||||
if (update.include) {
|
||||
base.include = update.include;
|
||||
if (!base.include) {
|
||||
base.include = update.include;
|
||||
} else {
|
||||
var saved = base.include;
|
||||
base.include = {};
|
||||
base.include[update.include] = [saved];
|
||||
}
|
||||
}
|
||||
if (update.collect) {
|
||||
base.collect = update.collect;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "loopback-datasource-juggler",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.1",
|
||||
"description": "LoopBack DataSoure Juggler",
|
||||
"keywords": [
|
||||
"StrongLoop",
|
||||
|
|
|
@ -350,6 +350,34 @@ describe('DataSource define model', function () {
|
|||
|
||||
});
|
||||
|
||||
it('should emit events during attach', function() {
|
||||
var ds = new DataSource('memory');
|
||||
var modelBuilder = new ModelBuilder();
|
||||
|
||||
var User = modelBuilder.define('User', {
|
||||
name: String
|
||||
});
|
||||
|
||||
var seq = 0;
|
||||
var dataAccessConfigured = -1;
|
||||
var dataSourceAttached = -1;
|
||||
|
||||
User.on('dataAccessConfigured', function (model) {
|
||||
dataAccessConfigured = seq++;
|
||||
assert(User.create);
|
||||
assert(User.hasMany);
|
||||
});
|
||||
|
||||
User.on('dataSourceAttached', function (model) {
|
||||
assert(User.dataSource instanceof DataSource);
|
||||
dataSourceAttached = seq++;
|
||||
});
|
||||
|
||||
ds.attach(User);
|
||||
assert.equal(dataAccessConfigured, 0);
|
||||
assert.equal(dataSourceAttached, 1);
|
||||
});
|
||||
|
||||
it('should not take unknown properties in strict mode', function (done) {
|
||||
var ds = new DataSource('memory');
|
||||
|
||||
|
@ -548,6 +576,15 @@ describe('DataSource define model', function () {
|
|||
|
||||
done();
|
||||
});
|
||||
|
||||
it('should allow an explicit remoting path', function () {
|
||||
var ds = new DataSource('memory');
|
||||
|
||||
var User = ds.define('User', {name: String, bio: String}, {
|
||||
http: { path: 'accounts' }
|
||||
});
|
||||
User.http.path.should.equal('/accounts');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -276,6 +276,34 @@ describe('relations', function () {
|
|||
}
|
||||
});
|
||||
|
||||
it('should allow to use include syntax on related data', function (done) {
|
||||
var Address = db.define('Address', {name: String});
|
||||
Patient.belongsTo(Address);
|
||||
Physician.create(function (err, physician) {
|
||||
physician.patients.create({name: 'a'}, function (err, patient) {
|
||||
Address.create({name: 'z'}, function (err, address) {
|
||||
patient.address(address);
|
||||
patient.save(function() {
|
||||
verify(physician);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
function verify(physician) {
|
||||
physician.patients({include: 'address'}, function (err, ch) {
|
||||
should.not.exist(err);
|
||||
should.exist(ch);
|
||||
ch.should.have.lengthOf(1);
|
||||
ch[0].addressId.should.equal(1);
|
||||
var address = ch[0].address();
|
||||
should.exist(address);
|
||||
address.should.be.an.instanceof(Address);
|
||||
address.name.should.equal('z');
|
||||
done();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it('should set targetClass on scope property', function() {
|
||||
should.equal(Physician.prototype.patients._targetClass, 'Patient');
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue