E43: Experience Simple Schema

The goal of this final Mongo experience is to learn about the Simple Schema and Collection2 packages, the standard approach to enforcing consistency in documents created for Mongo collections in Meteor.

Preview

This is not a practice WOD because I could not find any Readings to introduce this material. So, please watch me do it first before trying it yourself:

Task 1: Initial setup

For this experience, we will build upon the code we used in the last experience.

  1. Create a branch of your meteor-mongo-practice repo called “simple-schema”.

  2. Publish this branch (i.e. push it to GitHub).

  3. Run meteor reset and meteor run to start up a fresh instance of the system.

  4. Retrieve http://localhost:3000 in your browser to see a client instance of your meteor app.

Task 2: Understand the problem: Add a bogus document to the People collection

Update the PeopleInitialization.js file to look like this:

import { PeopleCollection } from '../imports/api/PeopleCollection.js';

if (PeopleCollection.find().count() === 0) {
  PeopleCollection.insert({ first: 'Philip', last: 'Johnson', age: 60, city: 'Kailua' });
  PeopleCollection.insert({ first: 'Joanne', last: 'Amberg', age: 58, city: 'Kailua' });
  PeopleCollection.insert({ first: 'Jenna', last: 'Corin', age: 31, city: 'Boulder Creek' });
  PeopleCollection.insert({ first: 'Katie', last: 'Kai', age: 25, city: 'Palo Alto' });
  PeopleCollection.insert({ first: 'Doris', last: 'Johnson', age: 93, city: 'Naples' });
}

PeopleCollection.insert({ animal: "Dog", name: "Koa", city: "Pearl City" });

Once the system restarts, verify that Koa was successfully added to the People collection.

What this illustrates is that by default, Mongo places no constraints on the documents that can be inserted into a collection. This is almost never what we want!

The standard way to enforce a structure on the documents in a Mongo collection using Meteor is through a package called “Simple Schema” (the npm package is called simpl-schema, I guess because the correctly spelled package name was already taken).

Task 3: Install Collection2 and Simple Schema

To make sure we don’t inadvertantly add dogs to our People collection, we will add two packages to our Meteor app: SimpleSchema and Collection2. Simple Schema provides a way to specify constraints on the structure of Mongo documents, and Collection2 provides a way to attach a Simple Schema to a Meteor collection such that violating these constraints when inserting or updating documents will trigger an error.

To install both of these packages, follow the Collection2 installation instructions.

Task 4: Define a schema for the PeopleCollection

Replace the contents of the PeopleCollection.js file with this:

import { Mongo } from 'meteor/mongo';
import SimpleSchema from 'simpl-schema';

const peopleSchema = new SimpleSchema(
  {
    first: String,
    last: String,
    age: SimpleSchema.Integer,
    city: String
  }
);

export const PeopleCollection = new Mongo.Collection('People');

PeopleCollection.attachSchema(peopleSchema);

The first two lines import the Mongo and SimpleSchema classes so we can refer to them in our code.

Next, we define a variable called peopleSchema, which is bound to an instance of a SimpleSchema. SimpleSchema takes an object as its argument which defines key-value pairs to specify constraints on a Mongo document. In this case, we are specifying that a document must have exactly four fields: first, last, age, and city. Three of those fields must be Strings and one must be an Integer.

The second to last line defines the PeopleCollection collection.

The last line attaches the peopleSchema to the PeopleCollection. (The “attachSchema” method is provided by the Collection2 package.) This last line means that any document added to the PeopleCollection must satisfy those constraints. If they don’t, then an error will be thrown.

Task 5: Reset and re-run the app

Now let’s check to see if the app runs correctly.

First, comment out the line that adds Koa the Dog to the PeopleCollection.

Then, invoke meteor reset and meteor run to restart your app with a fresh database.

You should see no errors in the console or in your client browser.

Task 6: Simple Schema in action: Koa the Dog denied!

Now, uncomment the line that adds Koa the Dog, and save the file. When Meteor restarts, you should see the following error in both the console and your browser:

Error: First is required
     at getErrorObject (packages/aldeed:collection2-core/collection2.js:453:15)
     at [object Object].doValidate (packages/aldeed:collection2-core/collection2.js:435:13)
     at [object Object].Mongo.Collection.(anonymous function) [as insert] (packages/aldeed:collection2-core/collection2.js:187:25)
     at meteorInstall.server.PeopleInitialization.js (server/PeopleInitialization.js:10:8)
     at fileEvaluate (packages/modules-runtime.js:333:9)
     at require (packages/modules-runtime.js:228:16)
     at /Users/philipjohnson/github/philipmjohnson/meteor-mongo-practice/app/.meteor/local/build/programs/server/app/app.js:116:1
     at /Users/philipjohnson/github/philipmjohnson/meteor-mongo-practice/app/.meteor/local/build/programs/server/boot.js:338:34
     at Array.forEach (native)
     at Function._.each._.forEach (/Users/philipjohnson/.meteor/packages/meteor-tool/.1.5.2.xbr9sy++os.osx.x86_64+web.browser+web.cordova/mt-os.osx.x86_64/dev_bundle/server-lib/node_modules/underscore/underscore.js:79:11)

The error was thrown as soon as SimpleSchema discovered a discrepancy between the schema (which requires that there be a field called “first”) and the document (which doesn’t have a “first” field).

Also, it’s vital to note that this stack trace identifies the exact line of code where the error occurred (Line 10 of PeopleInitialization.js). So, it’s easy to see that the problem is with the attempt to insert Koa the Dog into the People collection.

If you again comment out the line (or delete it), then Meteor will restart and everything will return to normal. (You will have to refresh the page in your browser).

Task 7: Commit your code to GitHub

When you have finished this exercise, commit your code to GitHub. This is the way we can check that you carried out the instructions in this assignment. It also provides sample code for you to look at in future to remind yourself of how Simple Schema works with Meteor and Mongo.

Summary

If you’ve followed along, you should now have a basic idea of how to use Simple Schema. In brief:

Submission instructions

By the time and date indicated in Laulima, submit this assignment via Laulima. To submit, please provide the URL to your GitHub repository.

This is not a practice WOD, so you do not have to time yourself.

You must now grant read access to this repo to the TA for your section. To do this: