0

I have 2 collections: Meteor.users and Projecs. Users collection have field "projects" which contains array of user's project's ids.

"projects" : [ 
  "jut6MHx6a7kSALPEP",  
  "XuJNvq7KTRheK6dSZ"
]

Also I have a publication for user's projects:

Meteor.publish('projects', function() {
  var userProjects = Meteor.users.findOne(this.userId).projects;
  return Projects.find({_id: {$in: userProjects}});
});

Everything works fine, but when I add new project (and update users ("projects" field) who are in this project) reactive publication doesn't works. Projects page doesn't contains recently added project. It works only when I refresh page.

Subscription made in router:

waitOn: function() { 
    return [
        Meteor.subscribe('projects')
        ]
  },

What should I do with this publication? Thanks a lot.

Clover
  • 3
  • 1
  • possible duplicate of [Meteor.publish: publish collection which depends on other collection](http://stackoverflow.com/questions/26398952/meteor-publish-publish-collection-which-depends-on-other-collection) – David Weldon Nov 20 '14 at 15:03

3 Answers3

0

Yea, this is a known "problem". Publish functions aren't reactive, so Meteor.users.findOne(this.userId).projects will only be evaluated when the client subscribes. You'll find a lot of information about this if you search for "meteor reactive joins", for example https://www.discovermeteor.com/blog/reactive-joins-in-meteor/

In your case, the clients will always have access to their array of project ids, right? Then the simplest solution would probably be to do something like this on the client:

Tracker.autorun(function(){
    var user = Meteor.user()
    if(user){
        Meteor.subscribe(user.projects)
    }
})

So, when the client notices that the array of project ids has changed, it renews the subscription (I'm unsure if passing user.projects to the subscribe call is necessary, but I'm a bit afraid that the subscription isn't is renewed if it's called with the same arguments as before).

Peppe L-G
  • 7,351
  • 2
  • 25
  • 50
0

This is happening because Meteor.users is not reactive. I don't know what the reason behind but I saw many developers, specially developers who try to get famous by publish really cool articles about their awesome application, exposing the tokens.

So if some idiot publish the Meteor.users to the browser, it's a security flaw. It would be even worst if it was reactive because the token would be updated in realtime. Maybe this a block to newbie who don't really know that they're doing. Just my opinion about this decision.

This collection is design to be used for managing users and after the login, it makes no sense to use to store data, as it is designed.

Mário
  • 1,603
  • 14
  • 24
0

Using the reactive-publish package (I am one of authors) you can do:

Meteor.publish('projects', function () {
  this.autorun(function (computation) {
    var userProjects = Meteor.users.findOne(this.userId, {fields: {projects: 1}}).projects;
    return Projects.find({_id: {$in: userProjects}});
  });
});

Just be careful to limit the first query only to projects so that autorun is not rerun for changes in other fields.

Mitar
  • 6,756
  • 5
  • 54
  • 86