From 1c65da0a1058c546d2ee4d419539a55344cbac5d Mon Sep 17 00:00:00 2001 From: nzouabi Date: Fri, 6 Apr 2018 23:33:22 +0200 Subject: [PATCH] Define children as a function --- README.md | 33 +++++++++++++++++++++++++++++++-- lib/publication.js | 6 ++++-- tests/client.js | 29 +++++++++++++++++++++++++++++ tests/server.js | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ba480d5..3f369b6 100644 --- a/README.md +++ b/README.md @@ -36,9 +36,11 @@ Arguments A function that returns a MongoDB cursor (e.g., `return Meteor.users.find({ active: true });`) - * **`children`** -- *array (optional)* + * **`children`** -- *array (optional)* or *function* - An array containing any number of object literals with this same structure + - An array containing any number of object literals with this same structure + - A function with top level documents as arguments. It helps dynamically build + the array based on conditions ( like documents fields values) * **`collectionName`** -- *string (optional)* @@ -85,6 +87,33 @@ Arguments } ``` + Example with children as function: + + ```javascript + { + find() { + return Notifications.find(); + }, + children(parentNotification) { + // children is a function that returns an array of objects. + // It takes parent documents as arguments and dynamically builds children array. + if (parentNotification.type === 'about_post') { + return [{ + find(notification) { + return Posts.find(parentNotification.objectId); + } + }]; + } + return [ + { + find(notification) { + return Comments.find(parentNotification.objectId); + } + } + ] + } + } + ``` ## Examples diff --git a/lib/publication.js b/lib/publication.js index eb0e72e..c64e1d6 100644 --- a/lib/publication.js +++ b/lib/publication.js @@ -10,7 +10,7 @@ class Publication { constructor(subscription, options, args) { check(options, { find: Function, - children: Match.Optional([Object]), + children: Match.Optional(Match.OneOf([Object], Function)), collectionName: Match.Optional(String), }); @@ -91,7 +91,9 @@ class Publication { } _publishChildrenOf(doc) { - _.each(this.childrenOptions, function createChildPublication(options) { + const children = _.isFunction(this.childrenOptions) ? + this.childrenOptions(doc, ...this.args) : this.childrenOptions; + _.each(children, function createChildPublication(options) { const pub = new Publication(this.subscription, options, [doc].concat(this.args)); this.publishedDocs.addChildPub(doc._id, pub); pub.publish(); diff --git a/tests/client.js b/tests/client.js index 95891dc..7b0e650 100644 --- a/tests/client.js +++ b/tests/client.js @@ -105,6 +105,21 @@ describe('publishComposite', () => { }, }); + testPublication('Should publish all post comment authors with children as Function', { + publication: 'allPostsWithChildrenAsFunction', + + testHandler: (onComplete) => { + const comments = Comments.find(); + + comments.forEach((comment) => { + const commentAuthor = Authors.findOne({ username: comment.author }); + asyncExpect(() => expect(commentAuthor).to.be.defined, onComplete); + }); + + onComplete(); + }, + }); + testPublication('Should publish one user\'s posts', { publication: 'userPosts', args: ['marie'], @@ -316,6 +331,20 @@ describe('publishComposite', () => { }, }); + testPublication('Should publish authors to both Authors with children as Function with Multip leLevel', { + publication: 'publishCommentAuthorsWithChildrenAsFunctionMultipleLevel', + + testHandler: (onComplete) => { + const marieAsAuthor = Authors.findOne({ username: 'marie' }); + const stephenAsCommentAuthor = CommentAuthors.findOne({ username: 'stephen' }); + + asyncExpect(() => expect(marieAsAuthor).to.be.defined, onComplete); + asyncExpect(() => expect(stephenAsCommentAuthor).to.not.be.defined, onComplete); + + onComplete(); + }, + }); + testPublication('Should publish two top level publications specified with a function', { publication: 'twoUsersPosts', args: ['marie', 'albert'], diff --git a/tests/server.js b/tests/server.js index 134d285..6448ca2 100644 --- a/tests/server.js +++ b/tests/server.js @@ -39,6 +39,17 @@ publishComposite('allPosts', { children: postPublicationChildren, }); +publishComposite('allPostsWithChildrenAsFunction', { + find() { + return Posts.find(); + }, + children: parentPost => (parentPost.author === 'albert' ? [{ + find(post) { + return Authors.find({ username: post.author }); + }, + }] : postPublicationChildren), +}); + publishComposite('userPosts', username => ({ find() { debugLog('userPosts', 'userPosts.find() called'); @@ -97,6 +108,30 @@ publishComposite('publishCommentAuthorsInAltClientCollection', { ], }); +publishComposite('publishCommentAuthorsWithChildrenAsFunctionMultipleLevel', { + find() { + return Posts.find(); + }, + children: [ + { + find(post) { + return Authors.find({ username: post.author }); + }, + }, + { + find(post) { + return Comments.find({ postId: post._id }); + }, + children: (parentComment, parentPost) => (parentComment.author === 'richard' ? [{ + collectionName: 'commentAuthors', + find(comment) { + return Authors.find({ username: comment.author }); + }, + }] : []), + }, + ], +}); + publishComposite('twoUsersPosts', (username1, username2) => [ { find() {