Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Meteor collection not updating subscription on client

I'm quite new on Meteor and Mongo and even if I don't want it, I need some relations.

I have a Collection called Feeds and another called UserFeeds where I have a feedid and a userid, and I publish the user feeds on the server like this:

Meteor.publish('feeds', function(){
    return Feeds.find({_id:{$in:_.pluck(UserFeeds.find({user:this.userId}).fetch(),'feedid')}});
});

I find the user on UserFeeds, fetch it (returns an array) and pluck it to have only the feedid field, and then find those feeds on the Feeds collection.

And subscribe on the client like this:

Deps.autorun(function(){
   Meteor.subscribe("feeds");
});

The problem is that when I add a new feed and a new userfeed the client doesn't receive the change, but when I refresh the page the new feed does appear.

Any idea of what I'm missing here?

Thanks.

like image 921
Beldar Avatar asked Mar 28 '13 11:03

Beldar


3 Answers

I've run into this, too. It turns out publish functions on the server don't re-run reactively: if they return a Collection cursor, as you're doing (and as most publish functions do), then the publish function will run once and Meteor will store the cursor and send down updates only when the contents of the cursor change. The important thing here is that Meteor will not re-run the publish function, nor, therefore, the Collection.find(query), when query changes. If you want the publish function to re-run, then the way I've done it so far is to set up the publish function to receive an argument. That way the client, whose collections do update reactively, can re-subscribe reactively. The code would look something like:

// client
Meteor.subscribe('user_feeds');

Deps.autorun(function(){ 
  var allFeeds = UserFeeds.find({user: Meteor.userId()}).fetch();
  var feedIds = _.pluck(allFeeds,'feedid');
  Meteor.subscribe('feeds',feedids);
});

// server
Meteor.publish('feeds',function(feedids) {
  return Feeds.find({_id: {$in: feedids}});
});

I believe the Meteorite package publish-with-relations is designed to solve this problem, although I haven't used it.

EDIT: I believe the publish function will re-run when the userId changes, which means that you can have a server-side check to make sure the user is logged in before publishing sensitive data.

like image 67
zorlak Avatar answered Oct 23 '22 21:10

zorlak


I think your problem is that .fetch() which you use here…

UserFeeds.find({user:this.userId}).fetch()

…removes the reactivity.

.fetch() returns an array instead of a cursor, and that array won't be reactive.

http://docs.meteor.com/#fetch

like image 33
Kristoffer K Avatar answered Oct 23 '22 23:10

Kristoffer K


try this ...

Meteor.autosubscribe(function(){
    Meteor.subscribe("feeds");
});

and in the Template JS ...

Template.templateName.feeds = function() 
  return Feeds.find() # or any specific call
};

in the HTML ...

{{#each feeds}}
   do some stuff
{{else}}
   no feed
{{/each}}
like image 1
real.netfly Avatar answered Oct 23 '22 21:10

real.netfly