Search code examples
meteoriron-router

Why call collection.find in an Iron Router controller


I have built a small meteor app based on code generated by the excellent Meteor Kitchen project. This code works and renders the collection to the page, but there is one thing I am confused about.

A subset of the code is here:

router.js

 this.route("articles", {path: "/articles", controller: "ArticlesController"});

ArticlesController

this.ArticlesController = RouteController.extend({
   template: "Articles",

   onBeforeAction: function() {
        this.next();
    },

   action: function(){
      if (this.isReady()) {
         this.render();
      } else {
         this.render("loading");
      }
   },

   isReady: function() {
      var ready = true;
      var subs = [ Meteor.subscribe('allArticles') ];
      _.each(subs, function(sub) {
         if(!sub.ready())
            ready = false;
      });
      return ready;
   },

   data: function() {
      return {
         articles: Articles.find({})
      };
   }
});

server/pubs/articles.js

Meteor.publish('allArticles', function() {
  return Articles.find({});
});


Meteor.publish('singleArticle', function(articleId) {
  check(articleId, String);
  return Articles.find({_id: articleId});
});

As I understand how this code is working, the following takes place:

(1) Collection is published via allArticles and singleArticle subscriptions
(2) ArticlesController subscribes to allArticles
(3) data function in the ArticlesController extracts the data (from the subscription?) to the articles array which is then exposed to the Blaze template.

Where I am confused: Why do we need to do a Articles.find({}) in the data function? Where do we access the allArticles data ... it seems we are going back to the Articles collection directly and how is that possible if we have subscribed only to allArticles ?


Solution

  • While you don't show it, I'm assuming you have the following line in your code, defined somewhere that will execute it on both the server, and the client:

      Articles       = new Mongo.Collection('articles');
    /*CollectionName = new Mongo.Collection('DBCollectionName');*/
    

    Docs. When this is executed on the server a Collection is created, and assigned to the variable name Articles. 'articles' is the name used to store this collection in MongoDB.

    When this is executed on the client, a mini mongo Collection is created. It initially will have no documents in it.

    Next you have server only code:

    Meteor.publish('allArticles', function() {
      return Articles.find({});
    });
    
    Meteor.publish('singleArticle', function(articleId) {
      check(articleId, String);
      return Articles.find({_id: articleId});
    });
    

    Docs. This defines two publications, 'allArticles' and 'singleArticle'. These are not Collections themselves, but are rules that specify a set of data that the server will publish, and a client may subscribe to. While these two publications return data from the Server's Articles collection, publications can return data from one or more collections, or by directly using the underlying ddp protocol you can publish data that comes from another data source (not mongodb).

    Next on the client you subscribe to a collection:

    Meteor.subscribe('allArticles')
    

    Docs. This call takes the name of a publication defined on the server ('allArticles'), and subscribes to it. The server then executes the publish function, and sends over ddp the set of data returned. This data is stored in the Client-side Mini Mongo Collection created above, and named Articles.

    Also the server will monitor the Articles collection for changes, and if the resultset of the 'allArticles' publication changes, will send these changes as updates to the client.

    So next you have the data function in your Controller (Client side).

    data: function() {
      return {
         articles: Articles.find({})
      };
    }
    

    Docs. This sets the data context for the render function.

    The reason this calls Articles.find rather than allArticles.find is because allArticles is not a collection, but was instead the name of the publication the client used to request the server send data, that was stored in the clients mini mongo collection named Articles.