I come from a strong Rails background, where seeding info into your database is super simple and intuitive.
My brother and I are building an open source "Golden path" Meteor application called Mercadera. We want people to have this clear example of how to build a great Meteor application with MongoDB and React.
https://github.com/danieltapia/mercadera
With that objective in mind, the database seed strategy had to be one that made sense, was easy to understand and was safe to use.
Here's our approach.
Structuring your seeds file.
See an example here:
The idea is that you write all your seed information in a simple file called seeds.js
. You wrap all of your document creation instructions inside a Meteor method.
We're using Astronomy for the data-layer in Meteor. It brings a nice solid foundation to any Meteor application in that you declare your structure in one place and that is your wall of defense for dirty data.
If you were to run this seeds file multiple times, it wouldn't add the same categories or cities twice, we have unique validators in our model.
Meteor.methods({
'Database.seed': function() {
// Create initial Category documents.
var categories = [
'Bienes Raices',
'Automoviles',
'Electrodomesticos',
'Computadoras'
];
_.forEach(categories, function(c) {
var category = new Category();
category.set({
name: c,
createdAt: new Date(),
totalListings: 0
});
category.generateSlug();
if (category.validate()) {
category.save();
}
});
// Create initial City documents.
var cities = [
'Santa Cruz',
'La Paz',
'Cochabamba',
'Tarija',
'Oruro',
'Sucre',
'Beni',
'Potosi',
'Pando'
];
_.forEach(cities, function(c) {
var city = new City();
city.set({
name: c,
createdAt: new Date(),
totalListings: 0
});
city.generateSlug();
if (city.validate()) {
city.save();
}
});
}
});
Running the seeds command.
All of our seed instructions are in a Meteor method, so you can run it like this:
$ meteor shell
> Meteor.call("Database.seed")
Run your meteor shell, then invoke your Meteor method. Simple.
That's all you need to seed your database with initial data. As an extra here are what our models look like:
Categories = new Mongo.Collection("categories");
Category = Astro.Class({
name: 'Category',
collection: Categories,
fields: {
name: {
type: 'string',
validator: [
Validators.required(null, "Type in a name for your Category."),
Validators.unique(null, "A category with this name already exists."),
Validators.minLength(4, "Your category name has to be at least 4 letters."),
Validators.maxLength(100, "Your category name can't be bigger than 100 letters.")
]
},
slug: {
type: 'string',
validator: [
Validators.unique(null, "A category with this name already exists.")
]
},
createdAt: {
type: 'date',
validator: [
Validators.required(),
]
},
totalListings: {
type: 'number'
}
},
methods: {
updateListingCount() {
Meteor.call("Category.updateListingCount", this._id);
},
generateSlug: function() {
var self = this;
Meteor.call("Helpers.generateSlug", this.name, function(error, response) {
self.set('slug', response);
});
}
}
});
And our City model:
Cities = new Mongo.Collection("cities");
City = Astro.Class({
name: 'City',
collection: Cities,
fields: {
name: {
type: 'string',
validator: [
Validators.required(null, "Type in a name for your City."),
Validators.unique(null, "A city with this name already exists."),
Validators.minLength(4, "Your city name has to be at least 4 letters."),
Validators.maxLength(100, "Your city name can't be bigger than 100 letters.")
]
},
slug: {
type: 'string',
validator: [
Validators.unique(null, "A city with this name already exists.")
]
},
createdAt: {
type: 'date',
validator: [
Validators.required(),
]
},
totalListings: {
type: 'number'
}
},
methods: {
updateListingCount() {
Meteor.call("City.updateListingCount", this._id);
},
generateSlug: function() {
var self = this;
Meteor.call("Helpers.generateSlug", this.name, function(error, response) {
self.set('slug', response);
});
}
}
});