Skip to content

Commit

Permalink
Added .index() method
Browse files Browse the repository at this point in the history
`.index()` will cause sequenice to call queryInterface.addIndex after the
model has been synced with the database
  • Loading branch information
saschagehlich committed Jan 6, 2014
1 parent 496d698 commit 8844c3e
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 13 deletions.
73 changes: 73 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ var path = require("path");
var fs = require("fs");
var _ = require("underscore");
var Sequelize = require("sequelize");
var Utils = Sequelize.Utils;
_.str = require("underscore.string");

function Sequenice(sequelize, options) {
Expand All @@ -25,6 +26,11 @@ function Sequenice(sequelize, options) {
this._loadModels();
this._resolveAssociations();
}

/**
* Available sequelize keywords
* @type {Array}
*/
Sequenice.RESOLVABLE_ASSOCIATION_OPTIONS = ["joinTableModel"];
Sequenice.ASSOCIATIONS = ["belongsTo", "hasMany", "hasOne"];
Sequenice.HOOKS = [
Expand Down Expand Up @@ -95,6 +101,7 @@ Sequenice.prototype._loadModel = function(modelPath) {
var setters = {};
var validators = {};
var hooks = {};
var indices = [];
var instanceMethods = {};
var classMethods = {};
var model, modelName, modelOptions;
Expand All @@ -115,6 +122,7 @@ Sequenice.prototype._loadModel = function(modelPath) {
this._attachValidatesHelperToModel(Model, validators);
this._attachAssociationHelpersToModel(Model);
this._attachHookHelpersToModel(Model, hooks);
this._attachIndexHelperToModel(Model, indices);
this._extractMethodsFromModel(Model, instanceMethods, classMethods);

// Call the model constructor so that our
Expand All @@ -133,6 +141,10 @@ Sequenice.prototype._loadModel = function(modelPath) {
};
model._model = this.sequelize.define(modelName, fields, modelOptions);

// Override the sync method so that it automatically
// adds the given indices
this._overrideSyncWithIndices(model._model, indices);

// Attach the real sequelize models to the modelsAttacher.
// Since modelsAttacher defaults to `global`, we will make
// the models globally available per default
Expand Down Expand Up @@ -246,6 +258,19 @@ Sequenice.prototype._attachHookHelpersToModel = function(modelClass, target) {
});
};

/**
* Adds a `index` prototype method to modelClass
* which will add a new index
* @param {Class} modelClass
* @param {Object} target
* @private
*/
Sequenice.prototype._attachIndexHelperToModel = function(modelClass, target) {
modelClass.prototype.index = function (attributes, options) {
target.push({ attributes: attributes, options: options });
};
};

/**
* Extracts instance methods and class methods from the given
* model class, excluding all methods in `modelClass._methodBlacklist`
Expand All @@ -271,4 +296,52 @@ Sequenice.prototype._extractMethodsFromModel = function(modelClass, instanceTarg
});
};

/**
* Overrides model.sync() to add incides after the syncing
* has been done
* @param {Model} model
* @param {Array} indices
* @private
*/
Sequenice.prototype._overrideSyncWithIndices = function(model, indices) {
var sync = model.sync;
var self = this;

// Gets called after syncing has been done
// Creates indices for this model
var addIndices = function (emitter, m) {
var chain = new Sequelize.Utils.QueryChainer();
var index;
for(var i = 0; i < indices.length; i++) {
index = indices[i];
chain.add(
self.sequelize.queryInterface.addIndex(model.tableName, index.attributes, index.options)
);
}

chain.run()
.success(function () {
emitter.emit("success", m);
})
.error(function (e) {
emitter.emit("error", e);
});
};

// Override syncing method so that it calls
// addIndices() afterwards
model.sync = function () {
var self = this;
return new Utils.CustomEventEmitter(function(emitter) {
sync.apply(self, arguments)
.success(function (m) {
addIndices(emitter, m);
})
.error(function (e) {
emitter.emit("error", e);
});
}).run();
};
};

module.exports = Sequenice;
40 changes: 30 additions & 10 deletions test/index.test.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
var should = require("should")
, Sequelize = require("sequelize")
, Sequenice = require("..")
, sequelize, sequenice
, models = {};
"use strict";
var should = require("should");
var Sequelize = require("sequelize");
var Sequenice = require("..");
var sequelize, sequenice;
var models = {};

before(function (done) {
sequelize = new Sequelize("sequenice_test", "travis", "");
sequelize = new Sequelize("sequenice_test", "root");
sequenice = new Sequenice(sequelize, {
modelsDirectory: __dirname + "/models",
modelsAttacher: models,
getterPrefix: "get",
setterPrefix: "set"
});
sequelize.sync({ force: true }).success(function () {
done()
var chain = new Sequelize.Utils.QueryChainer();

chain.add(sequelize.dropAllSchemas());
chain.add(sequelize.sync());

chain.run().success(function () {
done();
}).failure(function (err) {
throw err[0][0];
throw err;
});
});

Expand Down Expand Up @@ -94,7 +100,7 @@ describe("sequenice example", function () {
describe("hooks", function () {
it("defines a `beforeCreate` hook", function (done) {
models.User.create().success(function (user) {
user.beforeCreateCalled.should.be.true;
user.beforeCreateCalled.should.equal(true);
done();
});
});
Expand All @@ -109,4 +115,18 @@ describe("sequenice example", function () {

done();
});

/**
* Indices
*/
it("creates indices", function (done) {
sequelize.queryInterface.showIndex("Users").success(function (indices) {
indices.length.should.equal(3);

indices[1].name.should.equal("IdName");
indices[2].name.should.equal("NameIsAdmin");

done();
});
});
});
13 changes: 10 additions & 3 deletions test/models/user.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use strict";
function User(s) {
/**
* Field declarations
Expand Down Expand Up @@ -30,14 +31,20 @@ function User(s) {
/**
* Validations
*/
this.validates("myValidationMethod")
this.validates("myValidationMethod");

/**
* Indices
*/
this.index(["id", "name"], { indexName: "IdName" });
this.index(["name", "isAdmin"], { indexName: "NameIsAdmin" });
}

User.classMethod = function() {};
User.prototype.instanceMethod = function() {};

User.prototype.getPrice = function() {
return "$" + (this.getDataValue('priceInCents') / 100);
return "$" + (this.getDataValue("priceInCents") / 100);
};

User.prototype.getPriceInCents = function() {
Expand All @@ -55,6 +62,6 @@ User.prototype.myBeforeCreateMethod = function(user, callback) {

User.prototype.myValidationMethod = function (callback) {
callback();
}
};

module.exports = User;

0 comments on commit 8844c3e

Please sign in to comment.