UNPKG

sequelize-fixture

Version:

util for building sequelize model fixtures, mostly useful for setting up test data.

294 lines (254 loc) 7.26 kB
var casual = require('casual'); module.exports = function(Sequelize) { 'use strict'; var _ = Sequelize.Utils._, DataTypes = Sequelize; Sequelize.prototype.fixtures = function () { }; Sequelize.Model.prototype.fixtures = function (options) { options = to_options(options); skip_sequelize_timestamp_items(options, this); var define = _.mapValues(this.rawAttributes, function (def, item) { return { def: def, gen: to_gen(options, item) || from_validate(def) || random(def) }; }); function generator(options) { var self = this; options = to_options(options); function gen_associate(model) { return new Sequelize.Utils.CustomEventEmitter(function(emitter) { var count = 0; _.chain(options.include) .filter(function(associate) { return self.getAssociation(associate.model, associate.as); }) .each(function(associate) { var option = _.extend({}, associate.fixture); if (associate.hasOwnProperty('include')) { option.include = associate.include; } associate = self.getAssociation(associate.model, associate.as); option = _.extend(option, { create: true, instance: model, accessors: associate.accessors }); count++; associate.target.fixtures(option) .proxy(emitter, { events: ['error'] }) .success(function() { count--; if (count === 0) { emitter.emit('success'); } }); }); if (count === 0) { emitter.emit('success'); } }).run(); } function build() { var data = _.mapValues(define, function(fn, item) { return (to_gen(options, item) || fn.gen)(options, fn.def); }); return self.build(data); } function build_datasets() { if (options.num < 2) { return build(); } var data = []; for (var i = 0, num = options.num; i < num; i++) { data.push(build()); } return data; } function create_datasets() { return new Sequelize.Utils.CustomEventEmitter(function(emitter) { var i, num, chainer = new Sequelize.Utils.QueryChainer(); if (options.instance && options.accessors && options.accessors.create) { for (i = 0, num = options.num; i < num; i++) { chainer.add(options.instance[options.accessors.create](build().values)); } } else { for (i = 0, num = options.num; i < num; i++) { chainer.add(build().save()); } } chainer.run() .proxy(emitter, { events: ['error'] }) .success(function(models) { var find = { where: {id:[]}, include: options.include }; var chainer = new Sequelize.Utils.QueryChainer(); _.each(models, function(model) { find.where.id.push(model.id); chainer.add(gen_associate(model)); }); chainer.run() .proxy(emitter, { events: ['error'] }) .success(function() { self.findAll(find) .proxy(emitter, { events: ['error'] }) .success(function(rows) { emitter.emit('success', rows); }); }); }); }).run(); } if (!options.create) { return build_datasets(); } return create_datasets(); } this.fixtures = generator; return this.fixtures(options); }; var random_fn = { INTEGER: function() { return casual.integer(1, Math.pow(2, 31) - 1); }, STRING: function() { return casual.string; }, TEXT: function() { return casual.text; }, BIGINT: function() { return casual.integer(1, Math.pow(2, 31) - 1); }, FLOAT: function() { return casual.double(1, Math.pow(2, 31) - 1); }, BOOLEAN: function() { return casual.integer() > 0; }, DATE: function() { return new Date(casual.unix_time); }, NOW: function() { return new Date(); }, BLOB: function() { return casual.text; }, DECIMAL: function() { return casual.double(1, Math.pow(2, 31) - 1); }, UUIDV1: function() { return casual.numerify('########-####-1###-####-############'); }, UUIDV4: function() { return casual.numerify('########-####-4###-####-############'); } }; random_fn.UUID = random_fn.UUIDV1; var validate = { isUrl: function() { return casual.url; }, isEmail: function() { return casual.email; }, isIP: function() { return casual.ip; }, isIPv4: function() { return casual.ip; } }; function from_validate(def) { if (!def.validate) { return; } for (var type in validate) { if (def.validate[type]) { return validate[type]; } } } function auto_increment(options) { if (options.gen_auto_increment) { return _.uniqueId(); } return null; } function unsupport(def) { if (!def.hasOwnProperty('default')) { return casual.numerify('###@unknow dataType'); } if (_.isFunction(def.default)) { return def.default(); } return def.default; } function random(def) { if (def.autoIncrement) { return auto_increment; } for (var type in random_fn) { var data_type = DataTypes[type]; if (def === data_type || def.type === data_type || def.originalType === data_type) { return random_fn[type]; } if (typeof data_type !== 'string' && def instanceof data_type) { return random_fn[type]; } } if (def.type) { if (!def.type._binary && def.type._length) { return random_fn.STRING; } } return function() { return unsupport(def); }; } function to_options(options) { if (typeof options === 'number') { options = {num: options}; } options = _.extend({define:{}}, options); options.num = Math.max(options.num, 1) || 1; if (options.hasOwnProperty('include')) { if (!options.include instanceof Array) { if (options.include.model) { options.include = [options.include]; } else { options.include = undefined; } } if (!options.hasOwnProperty('create')) { options.create = !!options.include; } } return options; } function skip_sequelize_timestamp_items(options, instance) { _.each(instance._timestampAttributes, function(item) { if (options.define.hasOwnProperty(item)) { return; } options.define[item] = null; }); } function to_gen(options, item) { if (!options.define.hasOwnProperty(item)) { return; } var cb = options.define[item]; if (_.isFunction(cb)) { return cb; } return function () { return cb; }; } };