From 0c28ccedac5bc4acff230b05c47629ede11a3f92 Mon Sep 17 00:00:00 2001 From: Fabien Franzen Date: Fri, 10 Oct 2014 14:24:25 +0200 Subject: [PATCH] Refactored inclusion The syntax is now consistent, regardless of using [] or {} for the include param. --- lib/dao.js | 16 +++++++------- lib/include.js | 15 ++++++++++--- test/include.test.js | 51 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 11 deletions(-) diff --git a/lib/dao.js b/lib/dao.js index cff2e52c..2a9b9734 100644 --- a/lib/dao.js +++ b/lib/dao.js @@ -803,19 +803,19 @@ DataAccessObject.find = function find(query, cb) { // This handles the case to return parent items including the related // models. For example, Article.find({include: 'tags'}, ...); // Try to normalize the include - var includes = query.include || []; - if (typeof includes === 'string') { - includes = [includes]; - } else if (!Array.isArray(includes) && typeof includes === 'object') { - includes = Object.keys(includes); - } + var includes = Inclusion.normalizeInclude(query.include || []); includes.forEach(function (inc) { + var relationName = inc; + if (utils.isPlainObject(inc)) { + relationName = Object.keys(inc)[0]; + } + // Promote the included model as a direct property - var data = obj.__cachedRelations[inc]; + var data = obj.__cachedRelations[relationName]; if(Array.isArray(data)) { data = new List(data, null, obj); } - obj.__data[inc] = data; + if (data) obj.__data[relationName] = data; }); delete obj.__data.__cachedRelations; } diff --git a/lib/include.js b/lib/include.js index d3efc608..e3307dbb 100644 --- a/lib/include.js +++ b/lib/include.js @@ -63,6 +63,13 @@ module.exports = Inclusion; function Inclusion() { } +/** + * Normalize includes - used in DataAccessObject + * + */ + +Inclusion.normalizeInclude = normalizeInclude; + /** * Enables you to load relations of several objects and optimize numbers of requests. * @@ -98,7 +105,7 @@ Inclusion.include = function (objects, include, cb) { } include = normalizeInclude(include); - + async.each(include, function(item, callback) { processIncludeItem(objects, item, callback); }, function(err) { @@ -107,9 +114,10 @@ Inclusion.include = function (objects, include, cb) { function processIncludeItem(objs, include, cb) { var relations = self.relations; - + var relationName; var subInclude = null, scope = null; + if (isPlainObject(include)) { relationName = Object.keys(include)[0]; if (include[relationName] instanceof IncludeScope) { @@ -122,8 +130,8 @@ Inclusion.include = function (objects, include, cb) { relationName = include; subInclude = null; } - var relation = relations[relationName]; + var relation = relations[relationName]; if (!relation) { cb(new Error('Relation "' + relationName + '" is not defined for ' + self.modelName + ' model')); @@ -183,6 +191,7 @@ Inclusion.include = function (objects, include, cb) { if (err) { return callback(err); } else { + defineCachedRelations(obj); obj.__cachedRelations[relationName] = result; diff --git a/test/include.test.js b/test/include.test.js index b68c8881..9021a724 100644 --- a/test/include.test.js +++ b/test/include.test.js @@ -144,6 +144,57 @@ describe('include', function () { done(); }); }); + + it('should fetch Users with include scope on Posts', function (done) { + User.find({ + include: {relation: 'posts', scope:{ + order: 'title DESC' + }} + }, function (err, users) { + should.not.exist(err); + should.exist(users); + users.length.should.equal(5); + + users[0].name.should.equal('User A'); + users[1].name.should.equal('User B'); + + var posts = users[0].posts(); + posts.should.be.an.array; + posts.should.have.length(3); + + posts[0].title.should.equal('Post C'); + posts[1].title.should.equal('Post B'); + posts[2].title.should.equal('Post A'); + + var posts = users[1].posts(); + posts.should.be.an.array; + posts.should.have.length(1); + posts[0].title.should.equal('Post D'); + + done(); + }); + }); + + it('should fetch Users with include scope on Passports', function (done) { + User.find({ + include: {relation: 'passports', scope:{ + where: { number: '2' } + }} + }, function (err, users) { + should.not.exist(err); + should.exist(users); + users.length.should.equal(5); + + users[0].name.should.equal('User A'); + users[0].passports().should.be.empty; + + users[1].name.should.equal('User B'); + var passports = users[1].passports(); + passports[0].number.should.equal('2'); + + done(); + }); + }); it('should fetch User - Posts AND Passports', function (done) { User.find({include: ['posts', 'passports']}, function (err, users) {