Merge pull request #626 from walkonsocial/include-issues
Fix for issues #622 & #623
This commit is contained in:
commit
bbe9cb350c
|
@ -272,7 +272,10 @@ Inclusion.include = function (objects, include, options, cb) {
|
|||
}
|
||||
else {
|
||||
if (polymorphic) {
|
||||
return includePolymorphic(cb);
|
||||
if (relation.type === 'hasOne') {
|
||||
return includePolymorphicHasOne(cb);
|
||||
}
|
||||
return includePolymorphicBelongsTo(cb);
|
||||
}
|
||||
if (relation.type === 'embedsOne') {
|
||||
return includeEmbeds(cb);
|
||||
|
@ -387,6 +390,7 @@ Inclusion.include = function (objects, include, options, cb) {
|
|||
var targetId = target[modelToIdName];
|
||||
var objList = targetObjsMap[targetId.toString()];
|
||||
async.each(objList, function (obj, next) {
|
||||
if (!obj) return next();
|
||||
obj.__cachedRelations[relationName].push(target);
|
||||
processTargetObj(obj, next);
|
||||
}, next);
|
||||
|
@ -464,6 +468,7 @@ Inclusion.include = function (objects, include, options, cb) {
|
|||
function linkManyToMany(target, next) {
|
||||
var objList = targetObjsMap[target[relation.keyTo].toString()];
|
||||
async.each(objList, function (obj, next) {
|
||||
if (!obj) return next();
|
||||
obj.__cachedRelations[relationName].push(target);
|
||||
processTargetObj(obj, next);
|
||||
}, next);
|
||||
|
@ -523,9 +528,14 @@ Inclusion.include = function (objects, include, options, cb) {
|
|||
function targetLinkingTask(next) {
|
||||
async.each(targets, linkManyToOne, next);
|
||||
function linkManyToOne(target, next) {
|
||||
var obj = objIdMap[target[relation.keyTo].toString()];
|
||||
obj.__cachedRelations[relationName].push(target);
|
||||
processTargetObj(obj, next);
|
||||
//fix for bug in hasMany with referencesMany
|
||||
var targetIds = [].concat(target[relation.keyTo]);
|
||||
async.each(targetIds, function (targetId, next) {
|
||||
var obj = objIdMap[targetId.toString()];
|
||||
if (!obj) return next();
|
||||
obj.__cachedRelations[relationName].push(target);
|
||||
processTargetObj(obj, next);
|
||||
}, next);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -534,10 +544,10 @@ Inclusion.include = function (objects, include, options, cb) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Handle Inclusion of Polymorphic BelongsTo/HasOne relation
|
||||
* Handle Inclusion of Polymorphic BelongsTo relation
|
||||
* @param callback
|
||||
*/
|
||||
function includePolymorphic(callback) {
|
||||
function includePolymorphicBelongsTo(callback) {
|
||||
var targetIdsByType = {};
|
||||
//Map for Indexing objects by their type and targetId for faster retrieval
|
||||
var targetObjMapByType = {};
|
||||
|
@ -612,6 +622,7 @@ Inclusion.include = function (objects, include, options, cb) {
|
|||
function linkOneToMany(target, next) {
|
||||
var objList = targetObjsMap[target[relation.keyTo].toString()];
|
||||
async.each(objList, function (obj, next) {
|
||||
if (!obj) return next();
|
||||
obj.__cachedRelations[relationName] = target;
|
||||
processTargetObj(obj, next);
|
||||
}, next);
|
||||
|
@ -623,6 +634,68 @@ Inclusion.include = function (objects, include, options, cb) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle Inclusion of Polymorphic HasOne relation
|
||||
* @param callback
|
||||
*/
|
||||
function includePolymorphicHasOne(callback) {
|
||||
var sourceIds = [];
|
||||
//Map for Indexing objects by their id for faster retrieval
|
||||
var objIdMap = {};
|
||||
for (var i = 0; i < objs.length; i++) {
|
||||
var obj = objs[i];
|
||||
// one-to-one: foreign key reference is modelTo -> modelFrom.
|
||||
// use modelFrom.keyFrom in where filter later
|
||||
var sourceId = obj[relation.keyFrom];
|
||||
if (sourceId) {
|
||||
sourceIds.push(sourceId);
|
||||
objIdMap[sourceId.toString()] = obj;
|
||||
}
|
||||
// sourceId can be null. but cache empty data as result
|
||||
defineCachedRelations(obj);
|
||||
obj.__cachedRelations[relationName] = null;
|
||||
}
|
||||
filter.where[relation.keyTo] = {
|
||||
inq: uniq(sourceIds)
|
||||
};
|
||||
relation.applyScope(null, filter);
|
||||
relation.modelTo.find(filter, targetFetchHandler);
|
||||
/**
|
||||
* Process fetched related objects
|
||||
* @param err
|
||||
* @param {Array<Model>} targets
|
||||
* @returns {*}
|
||||
*/
|
||||
function targetFetchHandler(err, targets) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
var tasks = [];
|
||||
//simultaneously process subIncludes
|
||||
if (subInclude && targets) {
|
||||
tasks.push(function subIncludesTask(next) {
|
||||
relation.modelTo.include(targets, subInclude, options, next);
|
||||
});
|
||||
}
|
||||
//process each target object
|
||||
tasks.push(targetLinkingTask);
|
||||
function targetLinkingTask(next) {
|
||||
async.each(targets, linkOneToOne, next);
|
||||
function linkOneToOne(target, next) {
|
||||
var sourceId = target[relation.keyTo];
|
||||
if (!sourceId) return next();
|
||||
var obj = objIdMap[sourceId.toString()];
|
||||
if (!obj) return next();
|
||||
obj.__cachedRelations[relationName] = target;
|
||||
processTargetObj(obj, next);
|
||||
}
|
||||
}
|
||||
|
||||
execTasksWithInterLeave(tasks, callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Inclusion of BelongsTo/HasOne relation
|
||||
* @param callback
|
||||
|
@ -680,6 +753,7 @@ Inclusion.include = function (objects, include, options, cb) {
|
|||
var targetId = target[relation.keyTo];
|
||||
var objList = objTargetIdMap[targetId.toString()];
|
||||
async.each(objList, function (obj, next) {
|
||||
if (!obj) return next();
|
||||
obj.__cachedRelations[relationName] = target;
|
||||
processTargetObj(obj, next);
|
||||
}, next);
|
||||
|
|
|
@ -1663,6 +1663,16 @@ describe('relations', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('should include polymorphic relation - author', function (done) {
|
||||
Author.findOne({include: 'avatar'}, function (err, author) {
|
||||
should.not.exists(err);
|
||||
var avatar = author.avatar();
|
||||
should.exist(avatar);
|
||||
avatar.name.should.equal('Avatar');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should find polymorphic relation with promises - reader', function (done) {
|
||||
Reader.findOne()
|
||||
.then(function (reader) {
|
||||
|
@ -1688,6 +1698,18 @@ describe('relations', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('should include inverse polymorphic relation - author', function (done) {
|
||||
Picture.findOne({where: {name: 'Avatar'}, include: 'imageable'},
|
||||
function (err, p) {
|
||||
should.not.exists(err);
|
||||
var imageable = p.imageable();
|
||||
should.exist(imageable);
|
||||
imageable.should.be.instanceof(Author);
|
||||
imageable.name.should.equal('Author 1');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should find inverse polymorphic relation - reader', function (done) {
|
||||
Picture.findOne({ where: { name: 'Mugshot' } }, function (err, p) {
|
||||
should.not.exists(err);
|
||||
|
@ -1843,6 +1865,28 @@ describe('relations', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('should include polymorphic relation - reader', function (done) {
|
||||
Reader.findOne({include: 'mugshot'},
|
||||
function (err, reader) {
|
||||
should.not.exists(err);
|
||||
var mugshot = reader.mugshot();
|
||||
should.exist(mugshot);
|
||||
mugshot.name.should.equal('Mugshot');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should include inverse polymorphic relation - reader', function (done) {
|
||||
Picture.findOne({where: {name: 'Mugshot'}, include: 'owner'},
|
||||
function (err, p) {
|
||||
should.not.exists(err);
|
||||
var owner = p.owner();
|
||||
should.exist(owner);
|
||||
owner.should.be.instanceof(Reader);
|
||||
owner.name.should.equal('Reader 1');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('polymorphic hasMany', function () {
|
||||
|
@ -2030,6 +2074,19 @@ describe('relations', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('should include the inverse of polymorphic relation - author',
|
||||
function (done) {
|
||||
Picture.findOne({where: {name: 'Sample'}, include: 'imageable'},
|
||||
function (err, p) {
|
||||
should.not.exist(err);
|
||||
var imageable = p.imageable();
|
||||
should.exist(imageable);
|
||||
imageable.should.be.instanceof(Author);
|
||||
imageable.name.should.equal('Author 2');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('polymorphic hasAndBelongsToMany through', function () {
|
||||
|
|
Loading…
Reference in New Issue