Merge pull request #78 from mitsos1os/issue-42

Support retrieved related models from remote loopback service
This commit is contained in:
Miroslav Bajtoš 2017-12-12 13:08:55 +01:00 committed by GitHub
commit d622ce5ed8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 185 additions and 7 deletions

View File

@ -49,7 +49,6 @@ module.exports = function(grunt) {
// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-mocha-test');
grunt.loadNpmTasks('grunt-contrib-jshint');
// Default task.
grunt.registerTask('default', ['unit', 'integration']);

View File

@ -211,10 +211,23 @@ RelationMixin.embedsMany = function embedsMany(modelTo, params) {
function defineRelationProperty(modelClass, def) {
Object.defineProperty(modelClass.prototype, def.name, {
get: function() {
var that = this;
var scope = function() {
return that['__get__' + def.name].apply(that, arguments);
const that = this;
const scope = function() {
const cachedEntities = that.__cachedRelations &&
that.__cachedRelations[def.name];
if (arguments.length || !cachedEntities) {
return that['__get__' + def.name].apply(that, arguments);
}
// return the cached data
if (Array.isArray(cachedEntities)) {
return cachedEntities.map(data => new def.modelTo(data));
} else {
return new def.modelTo(cachedEntities);
}
};
scope.count = function() {
return that['__count__' + def.name].apply(that, arguments);
};

View File

@ -87,7 +87,17 @@ RemoteConnector.prototype.resolve = function(Model) {
// setup a remoting type converter for this model
remotes.defineObjectType(Model.modelName, function(data) {
return new Model(data);
const model = new Model(data);
// process cached relations
if (model.__cachedRelations) {
for (const relation in model.__cachedRelations) {
const relatedModel = model.__cachedRelations[relation];
model.__data[relation] = relatedModel;
}
}
return model;
});
};

View File

@ -11,7 +11,8 @@ const loopback = require('loopback');
const TaskEmitter = require('strong-task-emitter');
describe('Remote model tests', function() {
let serverApp, ServerModel, clientApp, ClientModel;
let serverApp, ServerModel, ServerRelatedModel, ServerModelWithSingleChild,
clientApp, ClientModel, ClientRelatedModel, ClientModelWithSingleChild;
beforeEach(function setupServer(done) {
const app = serverApp = helper.createRestAppAndListen();
@ -19,10 +20,46 @@ describe('Remote model tests', function() {
ServerModel = app.registry.createModel({
name: 'TestModel',
properties: helper.userProperties,
properties: helper.getUserProperties(),
options: {
forceId: false,
relations: {
children: {
type: 'hasMany',
model: 'ChildModel',
foreignKey: 'parentId',
},
},
},
});
ServerModelWithSingleChild = app.registry.createModel({
name: 'TestModelWithSingleChild',
properties: helper.getUserProperties(),
options: {
forceId: false,
relations: {
child: {
type: 'hasOne',
model: 'ChildModel',
foreignKey: 'parentId',
},
},
},
});
ServerRelatedModel = app.registry.createModel({
name: 'ChildModel',
properties: {
note: {type: 'text'},
parentId: {type: 'number'},
},
options: {forceId: false},
});
app.model(ServerModel, {dataSource: db});
app.model(ServerRelatedModel, {dataSource: db});
app.model(ServerModelWithSingleChild, {dataSource: db});
serverApp.locals.handler.on('listening', function() { done(); });
});
@ -31,15 +68,56 @@ describe('Remote model tests', function() {
const app = clientApp = loopback({localRegistry: true});
const remoteDs = helper.createRemoteDataSource(clientApp, serverApp);
ClientRelatedModel = app.registry.createModel({
name: 'ChildModel',
properties: {
note: {type: 'text'},
parentId: {type: 'number'},
},
options: {
strict: true,
},
});
ClientModel = app.registry.createModel({
name: 'TestModel',
properties: helper.getUserProperties(),
options: {
relations: {
children: {
type: 'hasMany',
model: 'ChildModel',
foreignKey: 'parentId',
},
},
strict: true,
},
});
ClientModelWithSingleChild = app.registry.createModel({
name: 'TestModelWithSingleChild',
properties: helper.getUserProperties(),
options: {
relations: {
child: {
type: 'hasOne',
model: 'ChildModel',
foreignKey: 'parentId',
},
},
strict: true,
},
});
app.model(ClientModel, {dataSource: remoteDs});
app.model(ClientRelatedModel, {dataSource: remoteDs});
app.model(ClientModelWithSingleChild, {dataSource: remoteDs});
});
afterEach(function() {
serverApp.locals.handler.close();
ServerModel = null;
ServerRelatedModel = null;
ClientModel = null;
});
@ -160,4 +238,82 @@ describe('Remote model tests', function() {
});
});
});
describe('Model find with include filter', function() {
let hasManyParent, hasManyChild, hasOneParent, hasOneChild;
beforeEach(givenSampleData);
it('should return also the included requested models', function() {
const parentId = hasManyParent.id;
return ClientModel.findById(hasManyParent.id, {include: 'children'})
.then(returnedUser => {
assert(returnedUser instanceof ClientModel);
const user = returnedUser.toJSON();
assert.equal(user.id, parentId);
assert.equal(user.first, hasManyParent.first);
assert(Array.isArray(user.children));
assert.equal(user.children.length, 1);
assert.deepEqual(user.children[0], hasManyChild.toJSON());
});
});
it('should return cachedRelated entity without call', function() {
const parentId = hasManyParent.id;
return ClientModel.findById(parentId, {include: 'children'})
.then(returnedUser => {
assert(returnedUser instanceof ClientModel);
const children = returnedUser.children();
assert.equal(returnedUser.id, parentId);
assert.equal(returnedUser.first, hasManyParent.first);
assert(Array.isArray(children));
assert.equal(children.length, 1);
assert(children[0] instanceof ClientRelatedModel);
assert.deepEqual(children[0].toJSON(), hasManyChild.toJSON());
});
});
it('should also work for single (non array) relations', function() {
const parentId = hasOneParent.id;
return ClientModelWithSingleChild.findById(parentId, {include: 'child'})
.then(returnedUser => {
assert(returnedUser instanceof ClientModelWithSingleChild);
const child = returnedUser.child();
assert.equal(returnedUser.id, parentId);
assert.equal(returnedUser.first, hasOneParent.first);
assert(child instanceof ClientRelatedModel);
assert.deepEqual(child.toJSON(), hasOneChild.toJSON());
});
});
function givenSampleData() {
return ServerModel.create({first: 'eiste', last: 'kopries'})
.then(parent => {
hasManyParent = parent;
return ServerRelatedModel.create({
note: 'mitsos',
parentId: parent.id,
id: 11,
});
})
.then(child => {
hasManyChild = child;
return ServerModelWithSingleChild.create({
first: 'mipos',
last: 'tora',
id: 12,
});
})
.then(parent => {
hasOneParent = parent;
return ServerRelatedModel.create({
note: 'mitsos3',
parentId: parent.id,
id: 13,
});
})
.then(child => {
hasOneChild = child;
});
}
});
});