Skip to content

Commit ebdc4ae

Browse files
committed
Fix loopbackio#1795 - Count issue with related models using though model
1 parent affa93a commit ebdc4ae

File tree

2 files changed

+71
-2
lines changed

2 files changed

+71
-2
lines changed

lib/scope.js

+42-2
Original file line numberDiff line numberDiff line change
@@ -431,11 +431,51 @@ function defineScope(cls, targetClass, name, params, methods, options) {
431431
options = {};
432432
}
433433
options = options || {};
434-
434+
// If there is a through model
435+
// run another query to apply filter on relatedModel(targetModel)
436+
// see github.com/strongloop/loopback-datasource-juggler/issues/1795
437+
let scopeOnRelatedModel = false;
438+
let queryRelated;
439+
if (this._scope && this._scope.collect &&
440+
where !== null && typeof where === 'object') {
441+
queryRelated = {
442+
relation: this._scope.collect,
443+
scope: {
444+
where: where,
445+
},
446+
};
447+
where = {};
448+
scopeOnRelatedModel = true;
449+
}
435450
const targetModel = definition.targetModel(this._receiver);
436451
const scoped = (this._scope && this._scope.where) || {};
437452
const filter = mergeQuery({where: scoped}, {where: where || {}});
438-
return targetModel.destroyAll(filter.where, options, cb);
453+
if (!scopeOnRelatedModel) {
454+
return targetModel.destroyAll(filter.where, options, cb);
455+
}
456+
return targetModel.find(filter, options, function(err, findData) {
457+
const relatedModel = targetModel.relations[queryRelated.relation].modelTo;
458+
const keyFrom = targetModel.relations[queryRelated.relation].keyFrom;
459+
const IdKey = idName(relatedModel);
460+
461+
// Merge queryRelated filter and targetId filter
462+
const buildWhere = function() {
463+
return {
464+
and: [
465+
{
466+
[IdKey]: collectTargetIds(findData, keyFrom || IdKey),
467+
},
468+
queryRelated.scope.where],
469+
};
470+
};
471+
if (queryRelated.scope.where !== undefined) {
472+
queryRelated.scope.where = buildWhere();
473+
} else {
474+
queryRelated.scope.where = {};
475+
queryRelated.scope.where[IdKey] = collectTargetIds(findData, keyFrom || IdKey);
476+
}
477+
return relatedModel.destroyAll(queryRelated.scope.where, options, cb);
478+
});
439479
}
440480

441481
function updateAll(where, data, options, cb) {

test/relations.test.js

+29
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,35 @@ describe('relations', function() {
702702
}
703703
});
704704

705+
it('should destroyAll all scoped record with promises based on related model properties', function(done) {
706+
let id;
707+
Physician.create()
708+
.then(function(physician) {
709+
return physician.patients.create({name: 'a'})
710+
.then(function(ch) {
711+
id = ch.id;
712+
return physician.patients.create({name: 'z'});
713+
})
714+
.then(function() {
715+
return physician.patients.create({name: 'c'});
716+
})
717+
.then(function() {
718+
return verify(physician);
719+
});
720+
}).catch(done);
721+
722+
function verify(physician) {
723+
return physician.patients.destroyAll({
724+
name: 'a',
725+
}, function(err, result) {
726+
if (err) return done(err);
727+
should.exist(result);
728+
result.count.should.equal(1);
729+
done();
730+
});
731+
}
732+
});
733+
705734
it('should build record on scope', function(done) {
706735
Physician.create(function(err, physician) {
707736
const patient = physician.patients.build();

0 commit comments

Comments
 (0)