Seeding data for a StrongLoop app

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!

Like This?

If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can also subscribe to the email feed to get notified of new posts.

Want to read more like this?