2

I have a situation which is best described using the following code:

Meteor.publish('users', function (name) {
  return Users.find({name: name});
});


Meteor.publish('posts', function (userId) {
  return Posts.find({userId: userId}, {sort: {insertDate: 1}});
});

A user has many posts. So, when the url is

http://example.com/john

So, to find the posts for a specific user I need to know the id of the user.

Now I have the following Controller:

UserController = RouteController.extend({
    onBeforeAction: function () {},
    waitOn: function () {
        var userSub = Meteor.subscribe('user', this.params.name);
        return [userSub]; 
    },
    data: function () { ... },
    action: function () {
        if (this.ready()) {
            this.render('user');
        }
        else {
           ;//this.render('loading');
        }
    }
});

Now I can only waitOn the user, but I also want to waitOn the Posts, but how can I do this, because to subscribe to the posts I need to know the userId:

Meteor.subscribe('posts', user._id);

Any suggestions ?

Jeanluca Scaljeri
  • 19,619
  • 37
  • 147
  • 259
  • You're right, but the selected answer is not what I'm looking for. However, the answer given by 'David Weldon' might be the only correct answer! – Jeanluca Scaljeri May 16 '14 at 15:49
  • That answer is the easiest to implement and understand, however it isn't reactive. So in your case if more posts are added they won't be published to the client. If that isn't an issue, you are all set. If it is, then I added some more ideas in my answer below. – David Weldon May 16 '14 at 16:17

1 Answers1

5

Joins in meteor are tricky at the moment. A lot of good information can be found in this post. For simple reactive joins, you can often do them directly in the route (explained in the "Joining On The Client" section). Here is an example for your users/posts join:

UserController = RouteController.extend({
  waitOn: function() {
    Meteor.subscribe('user', this.params.name);
  },
  data: function() {
    return Users.findOne({name: this.params.name});
  },
  onBeforeAction: function() {
    if (this.data()) {
      var userId = this.data()._id;
      this.subscribe('posts', userId).wait();
    }
  }
});

As mentioned in the comments above, if you are looking for a non-reactive join you can see my answer here. For reactive joins on the server, I'd recommend this question.

Community
  • 1
  • 1
David Weldon
  • 59,944
  • 10
  • 136
  • 139
  • thanks a lot for the answer and the very useful links!! +1 – Jeanluca Scaljeri May 16 '14 at 19:12
  • 1
    This didn't quite work for me I think the irouter api has changed a since the original post but putting the code from onBeforeAction into a subscriptions block made this work. From what i understand you can't call wait in a onBeforeAction – Nath Nov 21 '14 at 11:17
  • 2
    Hi, I find using `Meteor.subscribe('posts', userId);` works fine, but as Nath found, I can't call `wait` in `onBeforeAction` - Nath, could you elaborate on how you put the code into a subscriptions block to make it work? Thanks! – Racing Tadpole Apr 10 '15 at 01:37
  • In the meantime, I found [radzserg's answer](http://stackoverflow.com/questions/21839428/using-iron-router-to-waiton-subscription-thats-dependent-on-data-from-a-doc-tha#answer-27980948) to the 'duplicate post' - to use the subscribe function's callback to add more to the wait queue - works for me. – Racing Tadpole Apr 10 '15 at 01:51