Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 36 additions & 17 deletions lib/waterline/utils/query/forge-stage-two-query.js
Original file line number Diff line number Diff line change
Expand Up @@ -873,28 +873,47 @@ module.exports = function forgeStageTwoQuery(query, orm) {
if (_.isEqual(query.populates[populateAttrName], {})) {
query.populates[populateAttrName] = true;
}
// Otherwise, this simply must be `true`. Otherwise it's invalid.
// Otherwise, this must either be `true` or a valid subcriteria containing only `omit` or `select`.
else {

if (query.populates[populateAttrName] !== true) {
// Only allow a plain dictionary with just `select` and/or `omit`.
// Anything else isn't valid for a singular ("model") association.
if (query.populates[populateAttrName] !== true && !(
_.isPlainObject(query.populates[populateAttrName]) &&
_.difference(Object.keys(query.populates[populateAttrName]), ['select', 'omit']).length === 0
)) {
throw buildUsageError(
'E_INVALID_POPULATES',
'Could not populate `'+populateAttrName+'`. '+
'This is a singular ("model") association, which means it never refers to '+
'more than _one_ associated record. So passing in subcriteria (i.e. as '+
'the second argument to `.populate()`) is not supported for this association, '+
'since it generally wouldn\'t make any sense. But that\'s the trouble-- it '+
'looks like some sort of a subcriteria (or something) _was_ provided!\n'+
'(Note that subcriterias consisting ONLY of `omit` or `select` are a special '+
'case that _does_ make sense. This usage will be supported in a future version '+
'of Waterline.)\n'+
'\n'+
'Here\'s what was passed in:\n'+
util.inspect(query.populates[populateAttrName], {depth: 5}),
query.using
'E_INVALID_POPULATES',
'Could not populate `'+populateAttrName+'`. '+
'This is a singular ("model") association, which means it never refers to '+
'more than _one_ associated record. So passing in subcriteria (i.e. as '+
'the second argument to `.populate()`) is not supported for this association, '+
'since it generally wouldn\'t make any sense. But that\'s the trouble-- it '+
'looks like some sort of a subcriteria (or something) _was_ provided!\n'+
'(Note that subcriterias consisting ONLY of `omit` or `select` are a special '+
'case that _does_ make sense.\n'+
'\n'+
'Here\'s what was passed in:\n'+
util.inspect(query.populates[populateAttrName], {depth: 5}),
query.using
);
}//-•

// Ensure that only `select` or `omit` is provided, but not both.
if (_.isPlainObject(query.populates[populateAttrName]) &&
query.populates[populateAttrName].select &&
query.populates[populateAttrName].omit) {
throw buildUsageError(
'E_INVALID_POPULATES',
'Could not populate `'+populateAttrName+'`. '+
'This is a singular ("model") association, and while subcriterias consisting '+
'ONLY of `omit` or `select` are supported, providing both `select` AND `omit` '+
'at the same time is not allowed.\n'+
'\n'+
'Here\'s what was passed in:\n'+
util.inspect(query.populates[populateAttrName], {depth: 5}),
query.using
);
}//-•
}//>-•

}
Expand Down
44 changes: 44 additions & 0 deletions test/unit/query/associations/populateArray.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,49 @@ describe('Collection Query ::', function() {
return done();
});
});

it('should allow populate with select subcriteria for singular associations', function(done) {
Car.find()
.populate('driver', {
select: ['name']
})
.exec(function(err, car) {
if (err) {
return done(err);
}

assert(car[0].driver);
return done();
});
});

it('should allow populate with omit subcriteria for singular associations', function(done) {
Car.find()
.populate('driver', {
omit: ['id']
})
.exec(function(err, car) {
if (err) {
return done(err);
}

assert(car[0].driver);
return done();
});
});

it('should throw error when both select and omit are provided together', function(done) {
Car.find()
.populate('driver', {
select: ['name'],
omit: ['id']
})
.exec(function(err, car) {
assert(err);
assert.equal(err.code, 'E_INVALID_POPULATES');
assert(err.message.indexOf('providing both `select` AND `omit`') > -1);
return done();
});
});
});
});