Add id of new document to array in existing document using collection-hooks

81 Views Asked by At

I've used matb33:collection-hooks to insert a document after inserting into another, is it possible to update an existing document following an insert? I'm trying to do the following:

  • within a template Box, whose data context has an _id of boxId, call a method to insert a new document into Targets collection
  • get the _id of the new document and add it to an array of the document with _id of boxId.

Since this refers to the new document in the hook, I can't figure out how to get the boxId to update the right document.

Final code here per Pawel's answer:

Template.Box.events({
    'click .add button': function(e) {
        e.preventDefault();

        var currentBoxId = this._id;
        var target = {
            ...
        };

        Meteor.call('targetAdd', target, currentBoxId, function(){});
    }
});

Meteor.methods({
    targetAdd: function(targetAttributes, currentBoxId) {
        check(this.userId, String);
        check(currentBoxId, String);
        check(targetAttributes, {
            ...
        });

        var target = _.extend(targetAttributes, {
            userId: user._id,
            submitted: new Date()
        });

        var targetId = Targets.insert(target);
        Boxes.update(currentBoxId, {$addToSet: {targets:targetId}});

        return {
            _id: targetId
        };
    }
});
2

There are 2 best solutions below

3
On BEST ANSWER

Collection hooks don't know and don't have dependency on where the document was inserted/updated (that is one of the points of collection hooks - it doesn't matter where the operation comes from, the hook should always behave the same way).

What is more, even your targetAdd method doesn't have the boxId already - you would have to pass it as one of the parameters.

So in this case, you should pass the boxId as a parameter to targetAdd method and modify the box document in the method.

Use the collection hooks only for cases when context of a collection operation is not important.

2
On

You can just pass boxId to method and then to new record, after it it will appear in hook:

Template.Box.events({
    'click .add button': function(e) {
        e.preventDefault();

        var target = {
            ...
        };

        Meteor.call('targetAdd', target, this._id, function(){});
    }
});

Meteor.methods({
    targetAdd: function(targetAttributes, boxId) {
        check(this.userId, String);
        check(boxId, String);
        check(targetAttributes, {
            ...
        });

        var target = _.extend(targetAttributes, {
            submitted: new Date(),
            boxId: boxId
        });

        var targetId = Targets.insert(target);

        return {
            _id: targetId
        };
    }
});

Targets.after.insert(function () {
    var targetId = this._id;
    var boxId    = this.boxId;
    Boxes.update({_id:boxId}, {$addToSet: {targets: targetId}}, function () {
    }); 
});