diff --git a/lib/links/extension.js b/lib/links/extension.js index 3427b06..d80e258 100644 --- a/lib/links/extension.js +++ b/lib/links/extension.js @@ -61,6 +61,10 @@ _.extend(Mongo.Collection.prototype, { } else { object = {_id: objectOrId}; } + + if (!object) { + throw new Meteor.Error(`We could not find any object with _id: "${objectOrId}" within the collection: ${this._name}`); + } } return linkData[name].createLink(object); diff --git a/lib/links/linker.js b/lib/links/linker.js index fe92fca..658bc55 100644 --- a/lib/links/linker.js +++ b/lib/links/linker.js @@ -24,12 +24,18 @@ export default class Linker { this._validateAndClean(); this._extendSchema(); - // if it's a virtual field make sure that when this is deleted, it will be removed from the references + // initialize cascade removal hooks. + if (linkConfig.autoremove) { + this._initAutoremove(); + } + if (this.isVirtual()) { - this._handleReferenceRemovalForVirtualLinks(); + // if it's a virtual field make sure that when this is deleted, it will be removed from the references + if (!linkConfig.autoremove) { + this._handleReferenceRemovalForVirtualLinks(); + } } else { this._initIndex(); - this._initAutoremove(); } } @@ -343,7 +349,7 @@ export default class Linker { } _initAutoremove() { - if (this.linkConfig.autoremove) { + if (!this.isVirtual()) { this.mainCollection.after.remove((userId, doc) => { this.getLinkedCollection().remove({ _id: { @@ -351,6 +357,15 @@ export default class Linker { } }) }) + } else { + this.mainCollection.after.remove((userId, doc) => { + const linker = this.mainCollection.getLink(doc, this.linkName); + const ids = linker.find({}, {fields: {_id: 1}}).fetch().map(item => item._id); + + this.getLinkedCollection().remove({ + _id: {$in: ids} + }) + }) } } } \ No newline at end of file diff --git a/lib/links/tests/main.js b/lib/links/tests/main.js index c06cbda..10e96f1 100644 --- a/lib/links/tests/main.js +++ b/lib/links/tests/main.js @@ -36,6 +36,11 @@ PostCollection.addLinks({ field: 'autoRemoveIds', autoremove: true }, + 'autoRemovingSelfComments': { + type: '*', + collection: CommentCollection, + field: 'autoRemovingSelfCommentsIds', + }, 'metaComments': { type: '*', collection: CommentCollection, @@ -69,6 +74,11 @@ CommentCollection.addLinks({ collection: PostCollection, inversedBy: 'comments' }, + autoRemovePosts: { + collection: PostCollection, + inversedBy: 'autoRemovingSelfComments', + autoremove: true + }, metaPost: { collection: PostCollection, inversedBy: 'metaComments' @@ -344,5 +354,34 @@ describe('Collection Links', function () { assert.equal(e.error, 'not-found'); done(); } + }); + + it('Should work with autoremoval from inversed and direct link', function () { + // autoremoval from direct side + let postId = PostCollection.insert({text: 'autoremove'}); + const postAutoRemoveCommentsLink = PostCollection.getLink(postId, 'autoRemoveComments'); + + postAutoRemoveCommentsLink.add({text: 'hello'}); + + assert.lengthOf(postAutoRemoveCommentsLink.find().fetch(), 1); + let commentId = postAutoRemoveCommentsLink.find().fetch()[0]._id; + + assert.isObject(CommentCollection.findOne(commentId)); + PostCollection.remove(postId); + assert.isUndefined(CommentCollection.findOne(commentId)); + + + // now from inversed side + commentId = CommentCollection.insert({text: 'autoremove'}); + + const commentAutoRemovePostsLink = CommentCollection.getLink(commentId, 'autoRemovePosts'); + commentAutoRemovePostsLink.add({text: 'Hello'}); + + assert.lengthOf(commentAutoRemovePostsLink.find().fetch(), 1); + postId = commentAutoRemovePostsLink.find().fetch()[0]._id; + + assert.isObject(PostCollection.findOne(postId)); + CommentCollection.remove(commentId); + assert.isUndefined(PostCollection.findOne(postId)); }) }); \ No newline at end of file