This is just a quick post as a followup to something I mentioned in my post yesterday on building a blog with Strongloop. I mentioned that while working on my application, I kept losing my temporary data as I was using the "In Memory" datasource that is the default persistence method for data. That's not a bug - in memory means exactly that - in memory - and as I restarted the app (using nodemon), I had to re-enter fake data to test.
While it takes all of three minutes to connect your app to Mongo, if you don't have Mongo (or MySQL, or a db in general), it would be nice to be able to stick with the simple RAM based system while prototyping.
One of the things I realized is that Strongloop will run a set of scripts inside the boot directory on startup. In theory, that could be used to set some seed data. Jordan Kasper (evangelist for StrongLoop, which sounds like a fun job, ahem) shared this script with me as an example:
var async = require('async');
var mysqlDatasourceName = 'mysql_dev';
var mongoDatasourceName = 'mongodb_dev';
module.exports = function(app) {
//data sources
var mongoDs = app.dataSources[mongoDatasourceName];
var mysqlDs = app.dataSources[mysqlDatasourceName];
//create all models
async.parallel({
reviewers: async.apply(createReviewers),
coffeeShops: async.apply(createCoffeeShops),
}, function(err, results) {
if (err) throw err;
createReviews(results.reviewers, results.coffeeShops, function(err) {
if (err) throw err;
console.log('> models created sucessfully');
});
});
//create reviewers
function createReviewers(cb) {
mongoDs.automigrate('Reviewer', function(err) {
if (err) return cb(err);
var Reviewer = app.models.Reviewer;
Reviewer.create([
{email: 'foo@bar.com', password: 'foobar'},
{email: 'john@doe.com', password: 'johndoe'},
{email: 'jane@doe.com', password: 'janedoe'}
], cb);
});
}
//create coffee shops
function createCoffeeShops(cb) {
mysqlDs.automigrate('CoffeeShop', function(err) {
if (err) return cb(err);
var CoffeeShop = app.models.CoffeeShop;
var shops = [
{name: 'Bel Cafe',openingHour:10, closingHour:18},
{name: 'Three Bees Coffee House',openingHour:6, closingHour:15},
{name: 'Caffe Artigiano',openingHour:17, closingHour:24},
];
//add city if it's in the model
if(CoffeeShop.definition.properties.hasOwnProperty('city')){
var cities = ['Vancouver', 'San Mateo'];
shops.forEach(function(shop, idx){
shop.city = cities[idx%2];
});
}
CoffeeShop.create(shops, cb);
});
}
//create reviews
function createReviews(reviewers, coffeeShops, cb) {
mongoDs.automigrate('Review', function(err) {
if (err) return cb(err);
var Review = app.models.Review;
var DAY_IN_MILLISECONDS = 1000 * 60 * 60 * 24;
Review.create([
{
date: Date.now() - (DAY_IN_MILLISECONDS * 4),
rating: 5,
comments: 'A very good coffee shop.',
publisherId: reviewers[0].id,
coffeeShopId: coffeeShops[0].id,
},
{
date: Date.now() - (DAY_IN_MILLISECONDS * 3),
rating: 5,
comments: 'Quite pleasant.',
publisherId: reviewers[1].id,
coffeeShopId: coffeeShops[0].id,
},
{
date: Date.now() - (DAY_IN_MILLISECONDS * 2),
rating: 4,
comments: 'It was ok.',
publisherId: reviewers[1].id,
coffeeShopId: coffeeShops[1].id,
},
{
date: Date.now() - (DAY_IN_MILLISECONDS),
rating: 4,
comments: 'I go here everyday.',
publisherId: reviewers[2].id,
coffeeShopId: coffeeShops[2].id,
}
], cb);
});
}
};
I'm still new to Strongloop and Loopback in general, but this makes sense. My needs were far simpler, so here is a script I came up with (and again, Jordan helped me make it better) that just writes to a model in the in-memory datasource.
var chalk = require('chalk');
console.log(chalk.magenta('Lets seed this app!'));
/*
This script is based on:
https://github.com/strongloop-training/coffee-time/blob/master/server/boot/create-sample-model-data.js
*/
module.exports = function(app) {
//sample data
var data = [
{
title:'Content One',
body:'Body One',
posted:new Date()
},
{
title:'Content Two',
body:"Body Two",
posted:new Date()
},
{
title:'Content Three',
body:'Body Three',
posted:new Date()
}
];
app.models.TestContent.create(data, function(err, records) {
if (err) { return console.log(chalk.red(err.message)); }
console.log(chalk.magenta('Done seeding data, '+records.length+' records created.'));
});
}
Pretty simple, and it works nicely.
But Wait - There's More!
So as I said up on top, a few hours after posting this, Rand Mckinney from StrongLoop shared this link with me: Data persistence. In this doc they mention that you can simply specify a JSON file for the datasource and the in memory data will persist to it. Like, seriously, exactly what I had wanted. Here is an example:
{
"db": {
"name": "db",
"connector": "memory",
"file": "mydata.json"
}
}
Still - probably - a bad idea in production - but as I said - this would be incredibly useful when prototyping!