Tuesday, July 3, 2007

Mechanizations - Towards an ActiveRecord for Gears

With the recent hoopla over ECMA/JavaScript on Rails, and the advent of Google Gears (albeit beta), there is definitely a potential bubble waiting to happen. It's reasonable to expect a lot of APIs and frameworks to appear around Gears, and around the idea of making the browser an even thicker client in general.

Towards that end, I started Mechanizations to ease development of Gears, and JavaScript applications in general. While it is very rudimentary at the moment, supporting only a basic RoR ActiveRecord's ConnectionAdapter-style API, I think it can still help others working with Gears. Eventually, I hope to evolve it into an ActiveRecord for Gears (who didn't think of how great it would be to have a JavaScript ActiveRecord when they first saw Gears?), and a more generic framework beyond that.

As an introduction, I think the following snippet from the tests for the GearsConnector object is useful:


testMigrate: function() {
var migrations = [
{ // version 0
up: function(c) {
c.createTable('test_table', {id: 'INTEGER', name: 'TEXT'});
},
down: function(c) {
c.dropTable('test_table');
}
},
{ // version 1
up: function(c) {
c.createTable('test_table1', {id: 'INTEGER'});
},
down: function(c) {
c.dropTable('test_table1');
}
},
{ // version 2
up: function(c) {
c.dropTable('test_table');
c.dropTable('test_table1');
},
down: function(c) {
c.createTable('test_table', {id: 'INTEGER', name: 'TEXT'});
c.createTable('test_table1', {id: 'INTEGER'});
}
},
{ // version 3
up: function(c) {
c.renameTable('test_table', 'test_table1');
},
down: function(c) {
c.renameTable('test_table1', 'test_table');
}
}
];

this.connector.migrate(migrations, 0);
assertEquals(this.connector.tables(), ['_migrations','test_table']);

this.connector.migrate(migrations, 2);
assertEquals(this.connector.tables(), ['_migrations']);

this.connector.migrate(migrations, -1);
assertEquals(this.connector.tables(), ['_migrations']);

// This migrations fails, so we remain at version -1
this.connector.migrate(migrations, 3);
assertEquals(this.connector.tables(), ['_migrations']);
}

Just a bit more from the test for select:

testSelect: function() {
this.connector.createTable('test_table', {id: 'INTEGER', name: 'TEXT'});
this.connector.insert('test_table', [0, 'R1']);
this.connector.insert('test_table', [1, 'R2']);
this.connector.insert('test_table', [2, 'R3']);
assertEquals(this.connector.select('test_table').length, 3);
assertEquals($.keys(this.connector.select('test_table', [])[0]).length, 2);
assertEquals($.keys(this.connector.select('test_table', ['*'])[0]).length, 2);
assertEquals(this.connector.select('test_table', {headers: true}).length, 4);
assertEquals(this.connector.select('test_table', {where: ['id=?', 0]}).length, 1);
assertEquals(this.connector.select(
'test_table', ['id'], {where: ['id>?', 0], limit: 1})[0]['test_table_id'], 1);
assertEquals(this.connector.select(
'test_table', {where: ['id>?', 0], limit: 1, offset: 1})[0]['id'], 2);
assertEquals(this.connector.select(
'test_table', ['id'], {orderBy: 'id DESC'})[0]['test_table_id'], 2);
this.connector.dropTable('test_table');
}

No comments: