Please Read! A few hours after posting this, a member of the StrongLoop team pointed out an alternative that did exactly what I wanted to accomplish in about one second of typing. I still think the core of this blog entry makes sense as is so I'm not editing it, but see the note at the bottom!

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:

https://github.com/strongloop-training/coffee-time/blob/master/server/boot/create-sample-model-data.js


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.

shot1

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!