If you want to compare your code with mine, here's how you can get the final version of Foosboom (warning - it might have code in there you don't recognize as it's from further on in the book):

git clone https://github.com/webtempest/foos.git
cd foos

Link to repo on Github.

Methods

So we've reached a point where some code really needs to be performed on the server instead of on the client. Namely our game creation code, which relies on a consistent createdAt time attribute.

Allowing the client to generate the timestamp opens our app to the risk of the time being set incorrectly, or at least inconsistently, as users can change their time on their system.

A remote function

A method is simply a remote function - a function that runs on the server. It's similar to making an AJAX call - but instead of specifying a URL we just use the method name. We'll also provide a callback to occur once the call is complete. Note that we've already been using methods unknowingly - create(), update() and remove() are all methods baked in by the Meteor team.

We shift the game creation logic to the server.

Let's begin by creating the method and testing it. Add this to the bottom of both/collections/games.js:

both/collections/games.js

...
Meteor.methods({
  gamesInsert: function(teamOneId, teamTwoId){
    var teamOne = Teams.findOne({_id: teamOneId});
    var teamTwo = Teams.findOne({_id: teamTwoId});

    var teamOneData = {
      _id: teamOne._id,
      name: teamOne.name,
      score: 0
    };

    var teamTwoData = {
      _id: teamTwo._id,
      name: teamTwo.name,
      score: 0
    };

    var game = {
      ownerId: Meteor.userId(),
      createdAt: new Date(),
      teams: [teamOneData, teamTwoData],
      completed: false
    };

    var gameId = Games.insert(game);

    // Update each team's cached array of game ids
    Teams.update({_id: teamOneData._id}, {$addToSet: { gameIds: gameId}});
    Teams.update({_id: teamTwoData._id}, {$addToSet: { gameIds: gameId}});

    // Copy Meteor.insert(), which just returns the _id
    return gameId;
  }
});

Since Meteor methods are callable by the client, we can test them in the browser console. As you can see, our method takes two team _ids as parameters, so we will have to use one of our three ways of searching data (browser console, Mongol and meteor mongo). I used Mongol to get just one team _id and used that twice for simplicity (we don't enforce the teams being different):

Testing our method with the help of Mongol

Upon running this I see a new game pop up in the UI, confirming it works correctly.

If you are wondering why it says undefined in the browser console even though our method returns gameId, it's because the gameId is passed to the callback as a parameter. The undefined is returned by Meteor.call(). To see this more clearly we can do the same as above but passing a callback:

Here we see where our method's returned `gameId` appears