Using Iron Router to waitOn subscription that's dependent on data from a doc that will come from another subscription
Asked Answered
V

3

9

I'm having trouble configuring the waitOn portion of a route where one of the subscription's parameters is determined by the value from a doc that comes from a different subscription.

The collections in play are Candidates and Interviews. An interview will have one and only one candidate. Here's some sample data:

candidate = {
    _id: 1
    firstName: 'Some',
    lastName: 'Developer'
    //other props
};

interview = { 
    _id: 1,
    candidateId: 1
    //other props
};

The route is configured as follows.

this.route('conductInterview', {
    path: '/interviews/:_id/conduct', //:_id is the interviewId
    waitOn: function () {
        return [
            Meteor.subscribe('allUsers'),
            Meteor.subscribe('singleInterview', this.params._id),
            // don't know the candidateId to lookup because it's stored
            // in the interview doc
            Meteor.subscribe('singleCandidate', ???), 
            Meteor.subscribe('questions'),
            Meteor.subscribe('allUsers')
        ];
    },
    data: function () {
        var interview = Interviews.findOne(this.params._id);
        return {
            interview: interview,
            candidate: Candidates.findOne(interview.candidateId);
        };
    }
});

The problem is that I don't have a candidateId to pass to the singleCandidate subscription in the waitOn method because it's stored in the interview doc.

I've thought of two possible solutions, but I don't really like either of them. The first is to change the route to something like /interviews/:_id/:candidateId/conduct. The second is to denormalize the data and store the candidate's info in the interview doc.

Are there any other options to accomplish this besides those two?

Vaunt answered 17/2, 2014 at 21:17 Comment(0)
P
2

You can change your publish function singleCandidate to take interviewId as paramater instead of candidateId and pass this.params._id

Plafond answered 17/2, 2014 at 22:15 Comment(1)
Duh...so simple. I couldn't see the forest for the trees on this one. I am using the singleCandidate publication elsewhere, but I'll add an interviewCandidate publication. Thanks!Vaunt
S
5

You may get some ideas by reading this post on reactive joins. Because you need to fetch the candidate as part of the route's data, it seems like the easiest way is just to publish both the interview and the candidate at the same time:

Meteor.publish('interviewAndCandidate', function(interviewId) {
  check(interviewId, String);

  var interviewCursor = Interviews.find(interviewId);
  var candidateId = interviewCursor.fetch()[0].candidateId;

  return [interviewCursor, Candidates.find(candidateId);];
});

However, this join is not reactive. If a different candidate gets assigned to the interview, the client will not be updated. I suspect that isn't a problem in this case though.

Sempstress answered 17/2, 2014 at 22:25 Comment(3)
Thanks. This is a great solution as well.Vaunt
what would the subscribe look like?Cleaning
@JoeC Meteor.subscribe('interviewAndCandidate')Sempstress
P
2

You can change your publish function singleCandidate to take interviewId as paramater instead of candidateId and pass this.params._id

Plafond answered 17/2, 2014 at 22:15 Comment(1)
Duh...so simple. I couldn't see the forest for the trees on this one. I am using the singleCandidate publication elsewhere, but I'll add an interviewCandidate publication. Thanks!Vaunt
A
2

I had similar problem I managed to solve it via callback in subscribe

http://docs.meteor.com/#/basic/Meteor-subscribe

For example you have user data with city ids, and you need to get city objects

 waitOn: ->
    router = @
    [
        Meteor.subscribe("currentUserData", () ->
          user = Meteor.user()
          return unless user
          cityIds = user.cityIds
          router.wait( Meteor.subscribe("cities", cityIds)) if cityIds        
        )
    ]
Arri answered 16/1, 2015 at 9:37 Comment(1)
Great! Callbacks are what I needed.Haith

© 2022 - 2024 — McMap. All rights reserved.