Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Incremental migrations #7

Merged
merged 2 commits into from

2 participants

@kishorenc

Added support for incremental migrations. Specifying a migration filename during migrate up or migrate down will incrementally migrate till the given migration.

Updated readme and added tests too.

@tj tj merged commit e4cea8a into tj:master
@tj
Owner
tj commented

thanks!

@kishorenc

The formatting on the Readme.md seems to have become messed up for the new stuff I added. I can send another pull request with that fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 98 additions and 22 deletions.
  1. +15 −0 Readme.md
  2. +11 −10 bin/migrate
  3. +33 −12 lib/set.js
  4. +39 −0 test/test.migrate.js
View
15 Readme.md
@@ -93,6 +93,21 @@ If we were to create another migration using `migrate create`, and then execute
$ migrate
up : migrates/004-coolest-owner.js
+You can also run migrations incrementally by specifying a migration.
+
+ $ migrate up 002-coolest-pet.js
+ up : migrations/000-add-pets.js
+ up : migrations/001-add-jane.js
+ up : migrations/002-add-owners.js
+ migration : complete
+
+This will run up-migrations upto (and including) `002-coolest-pet.js`. Similarly you can run down-migrations upto (and including) a specific migration, instead of migrating all the way down.
+
+ $ migrate down 001-add-jane.js
+ down : migrations/002-add-owners.js
+ down : migrations/001-add-jane.js
+ migration : complete
+
## License
(The MIT License)
View
21 bin/migrate
@@ -40,8 +40,8 @@ var usage = [
, ''
, ' Commands:'
, ''
- , ' down migrate down'
- , ' up migrate up (the default command)'
+ , ' down [name] migrate down till given migration'
+ , ' up [name] migrate up till given migration (the default command)'
, ' create [title] create a new migration file with optional [title]'
, ''
].join('\n');
@@ -142,19 +142,19 @@ try {
var commands = {
/**
- * up
+ * up [name]
*/
- up: function(){
- performMigration('up');
+ up: function(migrationName){
+ performMigration('up', migrationName);
},
/**
- * down
+ * down [name]
*/
- down: function(){
- performMigration('down');
+ down: function(migrationName){
+ performMigration('down', migrationName);
},
/**
@@ -206,7 +206,7 @@ function create(name) {
* @param {Number} direction
*/
-function performMigration(direction) {
+function performMigration(direction, migrationName) {
migrate('migrations/.migrate');
migrations().forEach(function(path){
var mod = require(process.cwd() + '/' + path);
@@ -224,7 +224,8 @@ function performMigration(direction) {
process.exit();
});
- set[direction]();
+ var migrationPath = (typeof migrationName === 'undefined') ? migrationName : ('migrations/' + migrationName);
+ set[direction](null, migrationPath);
}
// invoke command
View
45 lib/set.js
@@ -81,8 +81,8 @@ Set.prototype.load = function(fn){
* @api public
*/
-Set.prototype.down = function(fn){
- this.migrate('down', fn);
+Set.prototype.down = function(fn, migrationName){
+ this.migrate('down', fn, migrationName);
};
/**
@@ -92,8 +92,8 @@ Set.prototype.down = function(fn){
* @api public
*/
-Set.prototype.up = function(fn){
- this.migrate('up', fn);
+Set.prototype.up = function(fn, migrationName){
+ this.migrate('up', fn, migrationName);
};
/**
@@ -104,7 +104,7 @@ Set.prototype.up = function(fn){
* @api public
*/
-Set.prototype.migrate = function(direction, fn){
+Set.prototype.migrate = function(direction, fn, migrationName){
var self = this;
fn = fn || function(){};
this.load(function(err, obj){
@@ -113,28 +113,49 @@ Set.prototype.migrate = function(direction, fn){
} else {
self.pos = obj.pos;
}
- self._migrate(direction, fn);
+ self._migrate(direction, fn, migrationName);
});
};
/**
+ * Get index of given migration in list of migrations
+ *
+ * @api private
+ */
+
+ function positionOfMigration(migrations, filename) {
+ for(var i=0; i<migrations.length; i++) {
+ if (migrations[i].title === filename) return i;
+ }
+ return -1;
+ }
+
+/**
* Perform migration.
*
* @api private
*/
-Set.prototype._migrate = function(direction, fn){
+Set.prototype._migrate = function(direction, fn, migrationName){
var self = this
- , migrations;
-
+ , migrations
+ , migrationPos;
+
+ if (typeof migrationName === 'undefined') {
+ migrationPos = (direction === 'up') ? this.migrations.length : 0;
+ } else if ((migrationPos = positionOfMigration(this.migrations,migrationName)) === -1) {
+ console.error("Could not find migration: "+migrationName);
+ process.exit(1);
+ }
+
switch (direction) {
case 'up':
- migrations = this.migrations.slice(this.pos);
+ migrations = this.migrations.slice(this.pos, migrationPos+1);
this.pos += migrations.length;
break;
case 'down':
- migrations = this.migrations.slice(0, this.pos).reverse();
- this.pos = 0;
+ migrations = this.migrations.slice(migrationPos, this.pos).reverse();
+ this.pos -= migrations.length;
break;
}
View
39 test/test.migrate.js
@@ -148,20 +148,59 @@ function testMigrationEvents() {
migrations.should.eql(expectedMigrations.reverse());
completed.should.equal(2);
assertNoPets();
+ testNamedMigrations();
});
});
}
+// test migrations when migration name is given
+
+function testNamedMigrations() {
+ assertNoPets();
+ set.up(function() {
+ assertFirstMigration();
+ set.up(function() {
+ assertSecondMigration();
+ set.down(function() {
+ assertFirstMigration();
+ set.up(function() {
+ assertSecondMigration();
+ set.down(function() {
+ set.pos.should.equal(1);
+ }, 'add girl ferrets');
+ },'add girl ferrets');
+ }, 'add girl ferrets');
+ },'add girl ferrets');
+ }, 'add guy ferrets');
+}
+
// helpers
function assertNoPets() {
db.pets.should.be.empty;
+ set.pos.should.equal(0);
}
function assertPets() {
db.pets.should.have.length(3);
db.pets[0].name.should.equal('tobi');
db.pets[0].email.should.equal('tobi@learnboost.com');
+ set.pos.should.equal(3);
+}
+
+function assertFirstMigration() {
+ db.pets.should.have.length(2);
+ db.pets[0].name.should.equal('tobi');
+ db.pets[1].name.should.equal('loki');
+ set.pos.should.equal(1);
+}
+
+function assertSecondMigration() {
+ db.pets.should.have.length(3);
+ db.pets[0].name.should.equal('tobi');
+ db.pets[1].name.should.equal('loki');
+ db.pets[2].name.should.equal('jane');
+ set.pos.should.equal(2);
}
assertPets.withDogs = function(){
Something went wrong with that request. Please try again.