Coder Social home page Coder Social logo

node-migrate-orm2's Introduction

migrate-orm2

Migrations using ORM2's model DSL leveraging Visionmedia's node-migrate.

Installation

npm install migrate-orm2

Usage

The example below uses MySQL. Locomote uses migrate-orm2 with Postgres. Testing was also done with SQLite3, though some driver issues were encountered.

Build a connection & construct the migrate-orm2 Task object:

var orm         = require('orm');
var MigrateTask = require('migrate-orm2');

orm.connect(connectionString, function (err, connection) {
  if (err) throw err;
  var task = new MigrateTask(connection.driver);
});

The Task constructor function can support options allowing for a custom migrations directory and/or coffeescript support (see 'Usage - opts' below).

A Task object offers three operations - generate, up and down.

Usage - generate

> task.generate('create-users', function(err, result){});
>   create : /Users/nicholasf/code/locomote/node-migrate-orm2/migrations/001-create-users.js

The 'migrations' folder is the default but can be overridden in the opts argument (see 'Usage - opts' below).

A skeleton migration file now exists and can be populated with the ORM2 DSL.

A simple example, taken from the tests:

exports.up = function (next) {
  this.createTable('test_table', {
    id     : { type : "serial", key: true }, // auto increment
    name   : { type : "text", required: true }
  }, next);
};

exports.down = function (next){
  this.dropTable('test_table', next);
};

Another example for adding or dropping a column:

exports.up = function(next){
  this.addColumn('agency', preferredProvider: {type: "text", defaultValue: '1G', required: true}, next);
}

exports.down = function(next){
  this.dropColumn('agency', 'preferredProvider', next);
}

An example of adding an index:

exports.up = function (next) {
  this.addIndex('agency_email_idx', {
    table: 'agency',
    columns: ['email'],
    unique: true
  }, next);
};

exports.down = function (next) {
  this.dropIndex('agency_email_idx', 'agency', next);
};

There are no built-in operations for inserting, updating, or deleting row data contained in tables. The execQuery operation, which can be used to execute any custom queries, can however be used to perform such actions:

exports.up = function (next) {
  this.execQuery('INSERT INTO agency (email) VALUES (?)', ['[email protected]'], next);
};

exports.down = function (next) {
  this.execQuery('DELETE FROM agency WHERE email = ?', ['[email protected]'], next);
};

The full list of operations available through this:

  • createTable
  • dropTable
  • addColumn
  • dropColumn
  • addIndex
  • dropIndex
  • addPrimaryKey
  • dropPrimaryKey
  • addForeignKey
  • dropForeignKey
  • execQuery

These operations are depicted in the examples folder.

We would like to add modifyColumn functionality in the future.

Usage - up and down

> task.up(function(e,r){});
>   up : migrations/001-create-users.js
  migration : complete

Alternatively, when there are many migrations, a filename can be specified:

> task.generate('create-servers', function(err, result){});
>   create : /Users/nicholasf/code/locomote/node-migrate-orm2/migrations/002-create-servers.js

> task.up('001-create-users.js', function(e,r){})
>   up : migrations/001-create-users.js
  migration : complete

This means 'run up to this migration then execute its up function, then stop.'

Usage - the orm_migrations table

Migrate-orm2 maintains an internal orm_migrations table which allows it to run from previous state.

Proceeding from the example immediately above:

> task.down(function(e,r){});
>   down : migrations/001-create-users.js
  migration : complete

Although there are two migration files, the up function reads from orm_migrations to find its current point. It then works out to call the down function of 001-create-users.js instead of 002-create-servers.js.

The orm_migrations table can be used to represent the history of migrations.

mysql> select * from orm_migrations;
+---------------------+-----------+--------------------------+
| migration           | direction | created_at               |
+---------------------+-----------+--------------------------+
| 001-create-users.js | up        | 2013-12-15T23:07:09.911Z |
| 001-create-users.js | up        | 2013-12-15T23:09:01.263Z |
| 001-create-users.js | down      | 2013-12-15T23:10:04.023Z |
+---------------------+-----------+--------------------------+
3 rows in set (0.00 sec)

This reflects the history above.

Usage - opts

The Task object can be modified to work from a different directory or to generate and cooperate with coffee-script migrations.

var task = new Task(connection, {dir: 'data/migrations', coffee: true});

Usage - orm-migrate

See https://github.com/nicholasf/node-orm-migrate for a command line tool.

♪  node-orm-migrate git:(master) ✗ migrate --help

  Usage: migrate [options]

  Options:

    -h, --help      output usage information
    -V, --version   output the version number
    -g, --generate  Generate a migration
    -u, --up        Run up migrations
    -d, --down      Run down migrations

Usage - grunt

We handcraft grunt and our tasks looks this.

Firstly, we have a helper file which knows how to build the connection and opts and invoke the Task object:

var MigrationTask = require('migrate-orm2');
var orm = require('orm');

exports.runMigration = function (operation, grunt, done) {
  orm.settings.set("connection.debug", true);
  orm.connect('mysql://root@localhost/ninja', function (err, connection) {
    if (err) throw(err);

    var migrationTask = new MigrationTask(
      connection.driver,
      { dir: 'data/migrations'}
    );
    migrationTask[operation](grunt.option('file'), done);
  });
};

Registering the Grunt tasks looks like this:

grunt.registerTask('migrate:generate', '', function () {
  var done = this.async();
  require('./tasks/db').runMigration('generate', grunt, done);
});

grunt.registerTask('migrate:up', '', function () {
  var done = this.async();
  require('./tasks/db').runMigration('up', grunt, done);
});

grunt.registerTask('migrate:down', '', function () {
  var done = this.async();
  require('./tasks/db').runMigration('down', grunt, done);
});

To generate a migration file or to indicate a direction:

grunt migrate:generate --file=create-users
grunt migrate:generate --file=create-servers
grunt migrate:up --file=001-create-users.js

Running Tests

Please note - running all of the tests together can produce database connection pooling problems. We are currently considering these.

Tests work in isolation and when the database is tuned for a greater amount of database connections.

Create test/config.js (see test/config.example.js for instructions)

npm test

This will run the tests against all configurations inside config.js. To run against a single config:

ORM_PROTOCOL=mysql node test/run
# OR
ORM_PROTOCOL=mysql mocha test/integration

Guideline to Contributing

Contributions are welcome. If you want to discuss or request a feature, please open an issue.

We will ask for test coverage of Pull Requests for most issues. Please see the current testing strategy in test/integration.

Contributors

  • nicholasf
  • dxg
  • vaskas
  • benkitzelman
  • sidorares
  • wolfeidau

This work is a melding of two underlying libraries:

node-migrate-orm2's People

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.