Meteor-Community-Packages / meteor-collection-hooks

Meteor Collection Hooks
https://atmospherejs.com/matb33/collection-hooks
MIT License
657 stars 92 forks source link

Hooks don't work inside observeChanges #151

Open dovrosenberg opened 9 years ago

dovrosenberg commented 9 years ago

I have a collection with a find hook attached to it. Inside of a meteor.publish, I have an observeChanges callback that is effectively doing a reactive join. The problem is that inside that callback, the find call always returns nothing. It appears to be because the userId isn't being properly retrieved inside the callback.

Meteor.publish('sample', function(id) {
var self = this;

var list1 = Collection1.find({_id:id});
var IDs = _.pluck(list1.fetch(), 'refID');

Collection2.find().count();  // this works fine

var handle = Collection1.observeChanges({
    added: function(id, fields) {
        Collection2.find().count();  // this always returns zero records
        self.added('contacts', fields.refID, Collection2.direct.findOne(fields.refID));  // this works fine
    }
});

// stop observing changes when publish ends
self.onStop(function() {
  return handle.stop();
});

self.ready();

return [list1, Collection2.find({_id:{$in:IDs}})];
});

Using the direct call works fine for my use case, but this seems like a bug, no?

mizzao commented 9 years ago

Note that in a method call, I think this might be because Meteor.bindEnvironment doesn't work properly inside observeChanges; I've seen some issues related to this such as meteor/meteor#907 and meteor/meteor#3455.

However, I see you're using a publish function (instead of a method call) there; that definitely won't work because we use a monkey-patch to store the userId during the publish and it will be forgotten when the callback is used. (https://github.com/matb33/meteor-collection-hooks/blob/master/collection-hooks.js#L268)

The problem is that the callback doesn't know it was started during the publish context, and has no idea what user it is supposed to supply to the find hook, so the find hook basically gets no user. The solution is to either set up the find without the hook after binding the userId in the closure yourself - you can use the hook anywhere else outside of publish functions.

Also, you might want to check out https://github.com/mizzao/meteor-partitioner if you're not using it already.

dovrosenberg commented 9 years ago

Makes sense. Thanks. Should meteor-partitioner solve this issue (great package, by the way)? I am using a fork of it customized for my particular application, and it's a partitioned collection that is displaying this behavior. But perhaps I cut out some important code in my customization?

turbobuilt commented 7 years ago

Is there a workaround that will accomplish the same thing? I don't understand the one mizzao said.

dovrosenberg commented 7 years ago

I could only work around it using .direct like above and then handling the transforms that the find hook would normally do manually.

turbobuilt commented 7 years ago

Bummer. Thanks for letting me know though.

zimme commented 7 years ago

From the first code example in this issue I believe this might be related to #215.