evolross
evolross

Reputation: 533

How do I use the results of a subscription for additional subscriptions at the route level?

I have a template that displays documents from three different collections Cars, CarPaints, and CarPaintTypes. I know I need all these upfront at the Router level. The template will show a Car document, all the CarPaints that reference that Car, and all the CarPaintTypes that reference the returned CarPaints respectively (think nested list). The route to the template takes an id from the URL that represents Car._id.

Both the Cars collection and CarPaints collection make use of the Car._id as a field (it's the native _id of the Cars collection and a field in the CarPaints collection) so that's easy. However, the CarPaintTypes uses the CarPaint._id as a reference to what CarPaint it belongs to.

So I have three publications:

Meteor.publish('car', function(carId) {
   return Cars.find({_id: carId});
});

Meteor.publish('carPaints', function(carId) {
   return CarPaints.find({carId: carId});
});

Meteor.publish('carPaintTypes', function(carPaintId) {
   return CarPaintTypes.find({carPaintId: carPaintId});
});

My route looks like:

this.route('car', {
    path: '/car/:_id',

    waitOn: function() {    

        return [Meteor.subscribe('car', this.params._id),
                Meteor.subscribe('carPaints', this.params._id)];
                // Can't figure out how to subscribe to or publish
                // the carPaintTypes using all the results of what gets
                // returned by 'carPaints'
    }   
});

My question is CarPaintTypes doesn't have the Car._id as a field, just the CarPaint._id to reference to a CarPaint document. Where and how I do take the results of the subscription to carPaints and pass each carPaint document that's returned to a subscription to carPaintTypes? Or is there a way to combine them all in the publication? Is it better to do it later on in my helpers? I figure since I know what I need at the route level, all the subscription calls should be in the route code.

Upvotes: 0

Views: 64

Answers (2)

evolross
evolross

Reputation: 533

With Kuba Wyrobek's help, I figured it out. For what I was trying to achieve, the publish looks like this:

Meteor.publish('carThings', function(carId){
    var carPaints = CarPaints.find({carId: carId}).fetch();
    return [
        Cars.find({_id: carId}),
        CarPaints.find({carId: carId}),
        CarPaintTypes.find({carPaintId: {$in: _.pluck(carPaints, "_id")}})
    ];
});

I didn't get that you could do manipulations inside your publication blocks. This is super cool and flexible. Thanks for your help.

Upvotes: 0

Kuba Wyrobek
Kuba Wyrobek

Reputation: 5273

You can grab all 3 cursors inside Meteor.publish method and simply return them:

Meteor.publish('carThings', function(carId){
   var carPaint =  CarPaints.findOne({carId:carId});
   return [
     Cars.find({_id: carId}),
     CarPaints.find({carId: carId}),
     CarPaintTypes.find({carPaintId: carPaint._id});
   ]
})

On client:

this.route('car', {
    path: '/car/:_id',

    waitOn: function() {    

        return [Meteor.subscribe('carThings', this.params._id)]


    }
}       

Upvotes: 1

Related Questions