2

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
        };
    }
});
Bren
  • 273
  • 1
  • 18
  • Where `boxId` coming from? I see it only in `after` hook, where this value is also available? – dr.dimitru Jan 17 '16 at 12:32
  • The boxId is the _id of the data context in the template in which the Targets.insert is triggered. But where should I refer to it for the hook? Can I define it in the hook (where I have the ???)? I tried Template.parentData but that returned undefined. Or do I need to pass it in from an earlier point? – Bren Jan 17 '16 at 13:08
  • Will you edit your question? – dr.dimitru Jan 17 '16 at 13:41

2 Answers2

0

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.

0

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 () {
    }); 
});
dr.dimitru
  • 2,645
  • 1
  • 27
  • 36
  • The boxId should not be added to the new Target record though. It should only be used to find the existing Box document to update by adding the new TargetId to an array. I have a use case elsewhere that will allow for the Target document to be used by other Box templates. Can I pass boxId through the method without adding to the new doc? – Bren Jan 17 '16 at 20:12
  • Yes, you can, but it won't be available in insert hook – dr.dimitru Jan 17 '16 at 20:26