不要怂,就是干,撸起袖子干!

Commit 38157a65 by Sascha Depold

migrations aren't synchronous anymore

1 parent 916473b5
...@@ -5,8 +5,6 @@ var moment = require("moment") ...@@ -5,8 +5,6 @@ var moment = require("moment")
module.exports = (function() { module.exports = (function() {
var Migration = function(migrator, path) { var Migration = function(migrator, path) {
var split = path.split('/')
this.migrator = migrator this.migrator = migrator
this.path = path this.path = path
this.filename = Utils._.last(this.path.split('/')) this.filename = Utils._.last(this.path.split('/'))
...@@ -16,7 +14,16 @@ module.exports = (function() { ...@@ -16,7 +14,16 @@ module.exports = (function() {
this.migrationId = parsed.id this.migrationId = parsed.id
this.date = parsed.date; this.date = parsed.date;
this.queryInterface = this.migrator.queryInterface this.queryInterface = this.migrator.queryInterface
this.undoneMethods = 0 }
for (var methodName in QueryInterface.prototype) {
if (QueryInterface.prototype.hasOwnProperty(methodName) && (typeof QueryInterface.prototype[methodName]) === 'function') {
(function(methodName) {
Migration.prototype[methodName] = function() {
return this.queryInterface[methodName].apply(this.queryInterface, arguments)
}
})(methodName)
}
} }
/////////////// ///////////////
...@@ -31,23 +38,11 @@ module.exports = (function() { ...@@ -31,23 +38,11 @@ module.exports = (function() {
} }
return { return {
id: parseInt(matches[1]), id: parseInt(matches[1], 10),
date: moment(matches.slice(2, 8).join('-'), 'YYYYMMDDHHmmss') date: moment(matches.slice(2, 8).join('-'), 'YYYYMMDDHHmmss')
} }
} }
Migration.migrationHasInterfaceCalls = function(func) {
var functionString = Utils.removeCommentsFromFunctionString(func.toString())
, hasCalls = false
for(var method in QueryInterface.prototype) {
var regex = new RegExp('[\\s\\n\\r]*\\.[\\s\\n\\r]*' + method)
hasCalls = hasCalls || regex.test(functionString)
}
return hasCalls
}
/////////////// ///////////////
// member ///// // member /////
/////////////// ///////////////
...@@ -59,22 +54,19 @@ module.exports = (function() { ...@@ -59,22 +54,19 @@ module.exports = (function() {
}) })
Migration.prototype.execute = function(options) { Migration.prototype.execute = function(options) {
var self = this
return new Utils.CustomEventEmitter(function(emitter) { return new Utils.CustomEventEmitter(function(emitter) {
options = Utils._.extend({ options = Utils._.extend({
method: 'up' method: 'up'
}, options || {}) }, options || {})
var onSuccess = function() { emitter.emit('success', null) } this.migration[options.method].call(null, this, DataTypes, function(err) {
, func = self.migration[options.method] if (err) {
emitter.emit('error', err)
extendMigrationWithQueryInterfaceMethods.call(self, onSuccess) } else {
func.call(null, self, DataTypes) emitter.emit('success', null)
}
if (!Migration.migrationHasInterfaceCalls(func)) })
onSuccess() }.bind(this)).run()
}).run()
} }
Migration.prototype.isBefore = function(dateString, options) { Migration.prototype.isBefore = function(dateString, options) {
...@@ -97,36 +89,5 @@ module.exports = (function() { ...@@ -97,36 +89,5 @@ module.exports = (function() {
return options.withoutEqual ? (date < this.date) : (date <= this.date) return options.withoutEqual ? (date < this.date) : (date <= this.date)
} }
// extends the Migration prototype with all methods of QueryInterface.prototype
// with additional tracking of start and finish. this is done in order to minimize
// asynchronous handling in migrations
var extendMigrationWithQueryInterfaceMethods = function(callback) {
var self = this
for(var method in QueryInterface.prototype) {
(function(_method) {
self[_method] = function() {
var emitter = self.QueryInterface
, args = Utils._.map(arguments, function(arg, _) { return arg })
self.undoneMethods++
// bind listeners to the query interface
// the event will have the same name like the method
self.queryInterface.on(_method, function(err) {
self.undoneMethods--
if (err) {
throw new Error(err)
} else {
(self.undoneMethods == 0) && callback && callback()
}
})
return self.queryInterface[_method].apply(self.queryInterface, args)
}
})(method)
}
}
return Migration return Migration
})() })()
...@@ -6,7 +6,7 @@ module.exports = (function() { ...@@ -6,7 +6,7 @@ module.exports = (function() {
var QueryInterface = function(sequelize) { var QueryInterface = function(sequelize) {
this.sequelize = sequelize this.sequelize = sequelize
this.QueryGenerator = require('./dialects/' + this.sequelize.options.dialect + '/query-generator') this.QueryGenerator = require('./dialects/' + this.sequelize.options.dialect + '/query-generator')
this.QueryGenerator.options = this.sequelize.options; this.QueryGenerator.options = this.sequelize.options
} }
Utils.addEventEmitter(QueryInterface) Utils.addEventEmitter(QueryInterface)
......
module.exports = { module.exports = {
up: function(migration, DataTypes) { up: function(migration, DataTypes, done) {
migration.createTable('Person', { migration
.createTable('Person', {
name: DataTypes.STRING, name: DataTypes.STRING,
isBetaMember: { isBetaMember: {
type: DataTypes.BOOLEAN, type: DataTypes.BOOLEAN,
...@@ -8,8 +9,9 @@ module.exports = { ...@@ -8,8 +9,9 @@ module.exports = {
allowNull: false allowNull: false
} }
}) })
.complete(done)
}, },
down: function(migration) { down: function(migration, DataTypes, done) {
migration.dropTable('Person') migration.dropTable('Person').complete(done)
} }
} }
module.exports = { module.exports = {
up: function() {}, up: function(migration, DataTypes, done) { done() },
down: function() {} down: function(migration, DataTypes, done) { done() }
} }
module.exports = { module.exports = {
up: function(migration, DataTypes) { up: function(migration, DataTypes, done) {
migration.renameTable('Person', 'User') migration.renameTable('Person', 'User').complete(done)
}, },
down: function(migration, DataTypes) { down: function(migration, DataTypes, done) {
migration.renameTable('User', 'Person') migration.renameTable('User', 'Person').complete(done)
} }
} }
module.exports = { module.exports = {
up: function(migration, DataTypes) { up: function(migration, DataTypes, done) {
migration.addColumn('User', 'signature', DataTypes.TEXT) migration
migration.addColumn('User', 'shopId', { type: DataTypes.INTEGER, allowNull: true }) .addColumn('User', 'isAdmin', { type: DataTypes.BOOLEAN, defaultValue: false, allowNull: false })
migration.addColumn('User', 'isAdmin', { type: DataTypes.BOOLEAN, defaultValue: false, allowNull: false }) .complete(function(err) {
if (err) {
done(err)
} else {
migration
.addColumn('User', 'signature', DataTypes.TEXT)
.complete(function(err) {
if (err) {
done(err)
} else {
migration.addColumn('User', 'shopId', { type: DataTypes.INTEGER, allowNull: true }).complete(done)
}
})
}
})
}, },
down: function(migration, DataTypes) { down: function(migration, DataTypes, done) {
migration.removeColumn('User', 'signature') migration.removeColumn('User', 'signature').complete(function(err) {
migration.removeColumn('User', 'shopId') if (err) {
migration.removeColumn('User', 'isAdmin') done(err)
} else {
migration.removeColumn('User', 'shopId').complete(function(err) {
if (err) {
done(err)
} else {
migration.removeColumn('User', 'isAdmin').complete(done)
}
})
}
})
} }
} }
module.exports = { module.exports = {
up: function(migration, DataTypes) { up: function(migration, DataTypes, done) {
migration.removeColumn('User', 'shopId') migration.removeColumn('User', 'shopId').complete(done)
}, },
down: function(migration, DataTypes) { down: function(migration, DataTypes, done) {
migration.addColumn('User', 'shopId', { type: DataTypes.INTEGER, allowNull: true }) migration.addColumn('User', 'shopId', { type: DataTypes.INTEGER, allowNull: true }).complete(done)
} }
} }
module.exports = { module.exports = {
up: function(migration, DataTypes) { up: function(migration, DataTypes, done) {
migration.changeColumn('User', 'signature', { migration.changeColumn('User', 'signature', {
type: DataTypes.STRING, type: DataTypes.STRING,
allowNull: false, allowNull: false,
defaultValue: 'Signature' defaultValue: 'Signature'
}) }).complete(done)
}, },
down: function(migration, DataTypes) {} down: function(migration, DataTypes, done) { done() }
} }
module.exports = { module.exports = {
up: function(migration, DataTypes) { up: function(migration, DataTypes, done) {
migration.renameColumn('User', 'signature', 'sig') migration.renameColumn('User', 'signature', 'sig').complete(done)
}, },
down: function(migration, DataTypes) { down: function(migration, DataTypes, done) {
migration.renameColumn('User', 'sig', 'signature') migration.renameColumn('User', 'sig', 'signature').complete(done)
} }
} }
if(typeof require === 'function') {
const buster = require("buster")
, QueryChainer = require("../lib/query-chainer")
, CustomEventEmitter = require("../lib/emitters/custom-event-emitter")
, Helpers = require('./buster-helpers')
, dialect = Helpers.getTestDialect()
, Migrator = require("../lib/migrator")
, Migration = require("../lib/migration")
}
buster.spec.expose()
buster.testRunner.timeout = 1000
describe(Helpers.getTestDialectTeaser("Migration"), function() {
describe('migrationHasInterfaceCalls', function() {
// the syntax in the following tests are correct
// don't touch them! the functions will get stringified below
var tests = [
{
topic: function(migration, DataTypes) {
migration.createTable()
},
expectation: true
},
{
topic: function(migration, DataTypes) {
// migration.createTable()
},
expectation: false
},
{
topic: function(migration, DataTypes) {
migration
.createTable()
},
expectation: true
},
{
topic: function(migration, DataTypes) {
migration.
createTable()
},
expectation: true
},
{
topic: function(migration, DataTypes) {
migration . createTable ()
},
expectation: true
},
{
topic: function(migration, DataTypes) {
/*
migration . createTable()
*/
},
expectation: false
},
{
topic: function(migration, DataTypes) {
migration/* noot noot */.createTable()
},
expectation: true
}
]
tests.forEach(function(test) {
it('correctly result in ' + test.expectation + ' for ' + test.topic.toString(), function() {
expect(Migration.migrationHasInterfaceCalls(test.topic)).toEqual(test.expectation)
})
})
})
})
...@@ -8,7 +8,7 @@ if(typeof require === 'function') { ...@@ -8,7 +8,7 @@ if(typeof require === 'function') {
} }
buster.spec.expose() buster.spec.expose()
buster.testRunner.timeout = 1000 buster.testRunner.timeout = 10000
describe(Helpers.getTestDialectTeaser("Migrator"), function() { describe(Helpers.getTestDialectTeaser("Migrator"), function() {
before(function(done) { before(function(done) {
...@@ -186,23 +186,18 @@ describe(Helpers.getTestDialectTeaser("Migrator"), function() { ...@@ -186,23 +186,18 @@ describe(Helpers.getTestDialectTeaser("Migrator"), function() {
}) })
describe('addColumn', function() { describe('addColumn', function() {
it('//adds a column to the user table', function(done) { it('adds a column to the user table', function(done) {
this.init({ from: 20111117063700, to: 20111205162700 }, function(migrator) { this.init({ from: 20111117063700, to: 20111205162700 }, function(migrator) {
migrator.migrate().success(function() { migrator.migrate().complete(function(err) {
this.sequelize.getQueryInterface().describeTable('User').success(function(data) { this.sequelize.getQueryInterface().describeTable('User').complete(function(err, data) {
var signature = data.signature var signature = data.signature
, isAdmin = data.isAdmin , isAdmin = data.isAdmin
, shopId = data.shopId , shopId = data.shopId
expect(signature.Field).toEqual('signature') expect(signature.allowNull).toEqual(true)
expect(signature.Null).toEqual('NO') expect(isAdmin.allowNull).toEqual(false)
expect(isAdmin.defaultValue).toEqual(false)
expect(isAdmin.Field).toEqual('isAdmin') expect(shopId.allowNull).toEqual(true)
expect(isAdmin.Null).toEqual('NO')
expect(isAdmin.Default).toEqual('0')
expect(shopId.Field).toEqual('shopId')
expect(shopId.Null).toEqual('YES')
done() done()
}) })
......
...@@ -159,7 +159,7 @@ describe(Helpers.getTestDialectTeaser("Sequelize"), function() { ...@@ -159,7 +159,7 @@ describe(Helpers.getTestDialectTeaser("Sequelize"), function() {
}.bind(this)) }.bind(this))
}) })
itEventually("doesn't save an instance if value is not in the range of enums", function(done) { it("//doesn't save an instance if value is not in the range of enums", function(done) {
this.Review.create({ status: 'fnord' }).error(function(err) { this.Review.create({ status: 'fnord' }).error(function(err) {
expect(1).toEqual(1) expect(1).toEqual(1)
done() done()
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!