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

Commit ab1b3093 by Jan Aagaard Meier

refactor DAO to use prototyping

1 parent 45fce2bf
...@@ -25,6 +25,10 @@ module.exports = (function() { ...@@ -25,6 +25,10 @@ module.exports = (function() {
this.identifier = this.options.foreignKey || Utils._.underscoredIf(Utils.singularize(this.target.tableName) + "Id", this.source.options.underscored) this.identifier = this.options.foreignKey || Utils._.underscoredIf(Utils.singularize(this.target.tableName) + "Id", this.source.options.underscored)
newAttributes[this.identifier] = { type: DataTypes.INTEGER } newAttributes[this.identifier] = { type: DataTypes.INTEGER }
Utils._.defaults(this.source.rawAttributes, newAttributes) Utils._.defaults(this.source.rawAttributes, newAttributes)
// Sync attributes to DAO proto each time a new assoc is added
this.target.DAO.prototype.attributes = Object.keys(this.target.DAO.prototype.rawAttributes);
return this return this
} }
......
...@@ -68,6 +68,10 @@ module.exports = (function() { ...@@ -68,6 +68,10 @@ module.exports = (function() {
Utils._.defaults(this.target.rawAttributes, newAttributes) Utils._.defaults(this.target.rawAttributes, newAttributes)
} }
// Sync attributes to DAO proto each time a new assoc is added
this.target.DAO.prototype.attributes = Object.keys(this.target.DAO.prototype.rawAttributes);
this.source.DAO.prototype.attributes = Object.keys(this.source.DAO.prototype.rawAttributes);
return this return this
} }
......
...@@ -31,6 +31,9 @@ module.exports = (function() { ...@@ -31,6 +31,9 @@ module.exports = (function() {
newAttributes[this.identifier] = { type: DataTypes.INTEGER } newAttributes[this.identifier] = { type: DataTypes.INTEGER }
Utils._.defaults(this.target.rawAttributes, newAttributes) Utils._.defaults(this.target.rawAttributes, newAttributes)
// Sync attributes to DAO proto each time a new assoc is added
this.target.DAO.prototype.attributes = Object.keys(this.target.DAO.prototype.rawAttributes);
return this return this
} }
......
...@@ -26,12 +26,6 @@ module.exports = (function() { ...@@ -26,12 +26,6 @@ module.exports = (function() {
// extract validation // extract validation
this.validate = this.options.validate || {} this.validate = this.options.validate || {}
// DAO prototype
this.DAO = function() {
DAO.apply(this, arguments);
};
Util.inherits(this.DAO, DAO);
} }
Object.defineProperty(DAOFactory.prototype, 'attributes', { Object.defineProperty(DAOFactory.prototype, 'attributes', {
...@@ -48,21 +42,60 @@ module.exports = (function() { ...@@ -48,21 +42,60 @@ module.exports = (function() {
get: function() { return this.QueryInterface.QueryGenerator } get: function() { return this.QueryInterface.QueryGenerator }
}) })
Object.defineProperty(DAOFactory.prototype, 'primaryKeyCount', { DAOFactory.prototype.init = function(daoFactoryManager) {
get: function() { return Utils._.keys(this.primaryKeys).length } var self = this;
})
this.daoFactoryManager = daoFactoryManager
Object.defineProperty(DAOFactory.prototype, 'hasPrimaryKeys', { this.primaryKeys = {};
get: function() { return this.primaryKeyCount > 0 } Utils._.each(this.attributes, function(dataTypeString, attributeName) {
if((attributeName != 'id') && (dataTypeString.indexOf('PRIMARY KEY') !== -1)) {
self.primaryKeys[attributeName] = dataTypeString
}
}) })
DAOFactory.prototype.init = function(daoFactoryManager) { this.primaryKeyCount = Utils._.keys(this.primaryKeys).length;
this.daoFactoryManager = daoFactoryManager this.options.hasPrimaryKeys = this.hasPrimaryKeys = this.primaryKeyCount > 0;
addDefaultAttributes.call(this) addDefaultAttributes.call(this)
addOptionalClassMethods.call(this) addOptionalClassMethods.call(this)
findAutoIncrementField.call(this) findAutoIncrementField.call(this)
// DAO prototype
this.DAO = function() {
DAO.apply(this, arguments);
};
Util.inherits(this.DAO, DAO);
this.DAO.prototype.rawAttributes = this.rawAttributes;
if (this.options.instanceMethods) {
Utils._.each(this.options.instanceMethods, function(fct, name) {
self.DAO.prototype[name] = fct
})
}
this.DAO.prototype.attributes = Object.keys(this.DAO.prototype.rawAttributes);
this.DAO.prototype.booleanValues = [];
this.DAO.prototype.defaultValues = {};
this.DAO.prototype.validators = {};
Utils._.each(this.rawAttributes, function (definition, name) {
if(((definition === DataTypes.BOOLEAN) || (definition.type === DataTypes.BOOLEAN))) {
self.DAO.prototype.booleanValues.push(name);
}
if(definition.hasOwnProperty('defaultValue')) {
self.DAO.prototype.defaultValues[name] = function() {
return Utils.toDefaultValue(definition.defaultValue);
}
}
if (definition.hasOwnProperty('validate')) {
self.DAO.prototype.validators[name] = definition.validate;
}
});
this.DAO.prototype.__factory = this;
this.DAO.prototype.hasDefaultValues = !Utils._.isEmpty(this.DAO.prototype.defaultValues);
return this return this
} }
...@@ -195,40 +228,12 @@ module.exports = (function() { ...@@ -195,40 +228,12 @@ module.exports = (function() {
} }
DAOFactory.prototype.build = function(values, options) { DAOFactory.prototype.build = function(values, options) {
var instance = new this.DAO(values, Utils._.extend(this.options, { hasPrimaryKeys: this.hasPrimaryKeys, factory: this }))
, self = this
options = options || {} options = options || {}
instance.__factory = this
Utils._.each(this.attributes, function(definition, name) { var self = this
//transform integer 0,1 into boolean , instance = new this.DAO(values, this.options)
if((definition.indexOf(DataTypes.BOOLEAN) !== -1) && (typeof instance[name] === "number")) {
instance[name] = (instance[name] !== 0)
}
//add default attributes
if(typeof instance[name] === 'undefined') {
var value = null
if(self.rawAttributes.hasOwnProperty(name) && self.rawAttributes[name].hasOwnProperty('defaultValue')) {
value = Utils.toDefaultValue(self.rawAttributes[name].defaultValue)
}
instance[name] = value
instance.addAttribute(name, value)
}
// add validation
if (self.rawAttributes.hasOwnProperty(name) && self.rawAttributes[name].hasOwnProperty('validate')) {
instance.setValidators(name, self.rawAttributes[name].validate)
}
})
Utils._.each(this.options.instanceMethods || {}, function(fct, name) { instance[name] = fct })
instance.isNewRecord = options.hasOwnProperty('isNewRecord') ? options.isNewRecord : true instance.isNewRecord = options.hasOwnProperty('isNewRecord') ? options.isNewRecord : true
instance.selectedValues = values
return instance return instance
} }
...@@ -237,17 +242,6 @@ module.exports = (function() { ...@@ -237,17 +242,6 @@ module.exports = (function() {
return this.build(values).save(fields) return this.build(values).save(fields)
} }
DAOFactory.prototype.__defineGetter__('primaryKeys', function() {
var result = {}
Utils._.each(this.attributes, function(dataTypeString, attributeName) {
if((attributeName != 'id') && (dataTypeString.indexOf('PRIMARY KEY') !== -1)) {
result[attributeName] = dataTypeString
}
})
return result
})
// private // private
var query = function() { var query = function() {
......
var Utils = require("./utils") var Utils = require("./utils")
, Mixin = require("./associations/mixin") , Mixin = require("./associations/mixin")
, Validator = require("validator") , Validator = require("validator")
, DataTypes = require("./data-types")
module.exports = (function() { module.exports = (function() {
var DAO = function(values, options) { var DAO = function(values, options) {
this.attributes = [] var self = this;
this.validators = {} // holds validation settings for each attribute this.__options = options;
this.__factory = options.factory || null // will be set by DAO.build if not present this.hasPrimaryKeys = options.hasPrimaryKeys;
this.__options = Utils._.extend({ this.selectedValues = values;
underscored: false,
hasPrimaryKeys: false,
timestamps: true,
paranoid: false
}, options || {})
initAttributes.call(this, values) initAttributes.call(this, values)
if (this.hasDefaultValues) {
Utils._.each(this.defaultValues, function (value, name) {
if(typeof self[name] === 'undefined') {
self.addAttribute(name, value());
}
})
}
if (this.booleanValues.length) {
this.booleanValues.forEach(function (name) {
//transform integer 0,1 into boolean
self[name] = !!self[name];
});
}
} }
Utils._.extend(DAO.prototype, Mixin.prototype) Utils._.extend(DAO.prototype, Mixin.prototype)
...@@ -242,7 +253,7 @@ module.exports = (function() { ...@@ -242,7 +253,7 @@ module.exports = (function() {
DAO.prototype.addAttribute = function(attribute, value) { DAO.prototype.addAttribute = function(attribute, value) {
this[attribute] = value this[attribute] = value
this.attributes.push(attribute) // this.attributes.push(attribute)
} }
DAO.prototype.setValidators = function(attribute, validators) { DAO.prototype.setValidators = function(attribute, validators) {
...@@ -265,7 +276,7 @@ module.exports = (function() { ...@@ -265,7 +276,7 @@ module.exports = (function() {
// set id to null if not passed as value // set id to null if not passed as value
// a newly created dao has no id // a newly created dao has no id
var defaults = this.__options.hasPrimaryKeys ? {} : { id: null } var defaults = this.hasPrimaryKeys ? {} : { id: null }
if(this.__options.timestamps) { if(this.__options.timestamps) {
defaults[this.__options.underscored ? 'created_at' : 'createdAt'] = new Date() defaults[this.__options.underscored ? 'created_at' : 'createdAt'] = new Date()
...@@ -276,6 +287,7 @@ module.exports = (function() { ...@@ -276,6 +287,7 @@ module.exports = (function() {
} }
} }
if (Utils._.size(defaults)) {
for (var attr in defaults) { for (var attr in defaults) {
var value = defaults[attr] var value = defaults[attr]
...@@ -284,6 +296,7 @@ module.exports = (function() { ...@@ -284,6 +296,7 @@ module.exports = (function() {
} }
} }
} }
}
return DAO return DAO
})() })()
...@@ -62,7 +62,7 @@ describe('BelongsTo', function() { ...@@ -62,7 +62,7 @@ describe('BelongsTo', function() {
Task.belongsTo(User) Task.belongsTo(User)
var task = Task.build({title: 'asd'}) var task = Task.build({title: 'asd'})
expect(task['UserId']).toBeNull() expect(task['UserId']).not.toBeDefined();
}) })
it("sets and gets the correct objects", function() { it("sets and gets the correct objects", function() {
......
...@@ -229,7 +229,8 @@ describe('DAO', function() { ...@@ -229,7 +229,8 @@ describe('DAO', function() {
it("doesn't update the updatedAt column", function() { it("doesn't update the updatedAt column", function() {
Helpers.async(function(done) { Helpers.async(function(done) {
User2.create({ username: 'john doe' }).success(function(johnDoe) { User2.create({ username: 'john doe' }).success(function(johnDoe) {
expect(johnDoe.updatedAt).toBeNull() // sqlite and mysql return undefined, whereas postgres returns null
expect([undefined, null].indexOf(johnDoe.updatedAt)).not.toBe(-1);
done() done()
}) })
}) })
......
...@@ -2,6 +2,7 @@ var config = module.exports ...@@ -2,6 +2,7 @@ var config = module.exports
config["node tests"] = { config["node tests"] = {
environment: "node", environment: "node",
timeout: 500,
rootPath: "../", rootPath: "../",
tests: [ tests: [
"spec/**/*.spec.js" "spec/**/*.spec.js"
......
...@@ -86,7 +86,7 @@ describe("[" + dialect.toUpperCase() + "] DAOFactory", function() { ...@@ -86,7 +86,7 @@ describe("[" + dialect.toUpperCase() + "] DAOFactory", function() {
}) })
expect(Task.build().title).toEqual('a task!') expect(Task.build().title).toEqual('a task!')
expect(Task.build().foo).toEqual(2) expect(Task.build().foo).toEqual(2)
expect(Task.build().bar).toEqual(null) expect(Task.build().bar).toEqual(undefined)
expect(Task.build().foobar).toEqual('asd') expect(Task.build().foobar).toEqual('asd')
expect(Task.build().flag).toEqual(false) expect(Task.build().flag).toEqual(false)
}) })
......
...@@ -6,6 +6,7 @@ if(typeof require === 'function') { ...@@ -6,6 +6,7 @@ if(typeof require === 'function') {
} }
buster.spec.expose() buster.spec.expose()
buster.timeout = 500;
describe("[" + dialect.toUpperCase() + "] DAO", function() { describe("[" + dialect.toUpperCase() + "] DAO", function() {
describe('validations', function() { describe('validations', function() {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!