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

Commit 03f18134 by Sascha Depold

removed old files

1 parent a2072da1
/**
* A port of the Rails/ActiveSupport Inflector class
* http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html
*/
var inflections = exports.inflections = {
plurals: [],
singulars: [],
uncountables: [],
humans: []
};
var PLURALS = inflections.plurals,
SINGULARS = inflections.singulars,
UNCOUNTABLES = inflections.uncountables,
HUMANS = inflections.humans;
/**
* Specifies a new pluralization rule and its replacement. The rule can either
* be a string or a regular expression. The replacement should always be a
* string that may include references to the matched data from the rule.
*/
var plural = function (rule, replacement) {
//inflections.uncountables.delete(rule) if rule.is_a?(String)
//inflections.uncountables.delete(replacement)
inflections.plurals.unshift([rule, replacement]);
}
/**
* Specifies a new singularization rule and its replacement. The rule can either
* be a string or a regular expression. The replacement should always be a
* string that may include references to the matched data from the rule.
*/
var singular = function (rule, replacement) {
//inflections.uncountables.delete(rule) if rule.is_a?(String)
//inflections.uncountables.delete(replacement)
inflections.singulars.unshift([rule, replacement]);
}
/**
* Add uncountable words that shouldn't be attempted inflected.
*/
var uncountable = function (word) {
inflections.uncountables.unshift(word);
}
/**
* Specifies a new irregular that applies to both pluralization and
* singularization at the same time. This can only be used for strings, not
* regular expressions. You simply pass the irregular in singular and plural
* form.
*
* Examples:
* irregular("octopus", "octopi");
* irregular("person", "people");
*/
var irregular = function (s, p) {
//inflections.uncountables.delete(singular);
//inflections.uncountables.delete(plural);
if (s.substr(0, 1).toUpperCase() == p.substr(0, 1).toUpperCase()) {
plural(new RegExp("(" + s.substr(0, 1) + ")" + s.substr(1) + "$", "i"), '$1' + p.substr(1));
plural(new RegExp("(" + p.substr(0, 1) + ")" + p.substr(1) + "$", "i"), '$1' + p.substr(1));
singular(new RegExp("(" + p.substr(0, 1) + ")" + p.substr(1) + "$", "i"), '$1' + s.substr(1));
} else {
plural(new RegExp(s.substr(0, 1).toUpperCase() + s.substr(1) + "$"), p.substr(0, 1).toUpperCase() + p.substr(1));
plural(new RegExp(s.substr(0, 1).toLowerCase() + s.substr(1) + "$"), p.substr(0, 1).toLowerCase() + p.substr(1));
plural(new RegExp(p.substr(0, 1).toUpperCase() + p.substr(1) + "$"), p.substr(0, 1).toUpperCase() + p.substr(1));
plural(new RegExp(p.substr(0, 1).toLowerCase() + p.substr(1) + "$"), p.substr(0, 1).toLowerCase() + p.substr(1));
singular(new RegExp(p.substr(0, 1).toUpperCase() + p.substr(1) + "$"), s.substr(0, 1).toUpperCase() + s.substr(1));
singular(new RegExp(p.substr(0, 1).toLowerCase() + p.substr(1) + "$"), s.substr(0, 1).toLowerCase() + s.substr(1));
}
}
/**
* Specifies a humanized form of a string by a regular expression rule or by a
* string mapping. When using a regular expression based replacement, the normal
* humanize formatting is called after the replacement.
*/
var human = function (rule, replacement) {
//inflections.uncountables.delete(rule) if rule.is_a?(String)
//inflections.uncountables.delete(replacement)
inflections.humans.push([rule, replacement]);
}
plural(/$/, "s");
plural(/s$/i, "s");
plural(/(ax|test)is$/i, "$1es");
plural(/(octop|vir)us$/i, "$1i");
plural(/(alias|status)$/i, "$1es");
plural(/(bu)s$/i, "$1ses");
plural(/(buffal|tomat)o$/i, "$1oes");
plural(/([ti])um$/i, "$1a");
plural(/sis$/i, "ses");
plural(/(?:([^f])fe|([lr])f)$/i, "$1$2ves");
plural(/(hive)$/i, "$1s");
plural(/([^aeiouy]|qu)y$/i, "$1ies");
plural(/(x|ch|ss|sh)$/i, "$1es");
plural(/(matr|vert|ind)(?:ix|ex)$/i, "$1ices");
plural(/([m|l])ouse$/i, "$1ice");
plural(/^(ox)$/i, "$1en");
plural(/(quiz)$/i, "$1zes");
singular(/s$/i, "")
singular(/(n)ews$/i, "$1ews")
singular(/([ti])a$/i, "$1um")
singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, "$1$2sis")
singular(/(^analy)ses$/i, "$1sis")
singular(/([^f])ves$/i, "$1fe")
singular(/(hive)s$/i, "$1")
singular(/(tive)s$/i, "$1")
singular(/([lr])ves$/i, "$1f")
singular(/([^aeiouy]|qu)ies$/i, "$1y")
singular(/(s)eries$/i, "$1eries")
singular(/(m)ovies$/i, "$1ovie")
singular(/(x|ch|ss|sh)es$/i, "$1")
singular(/([m|l])ice$/i, "$1ouse")
singular(/(bus)es$/i, "$1")
singular(/(o)es$/i, "$1")
singular(/(shoe)s$/i, "$1")
singular(/(cris|ax|test)es$/i, "$1is")
singular(/(octop|vir)i$/i, "$1us")
singular(/(alias|status)es$/i, "$1")
singular(/^(ox)en/i, "$1")
singular(/(vert|ind)ices$/i, "$1ex")
singular(/(matr)ices$/i, "$1ix")
singular(/(quiz)zes$/i, "$1")
singular(/(database)s$/i, "$1")
irregular("person", "people");
irregular("man", "men");
irregular("child", "children");
irregular("sex", "sexes");
irregular("move", "moves");
irregular("cow", "kine");
uncountable("equipment");
uncountable("information");
uncountable("rice");
uncountable("money");
uncountable("species");
uncountable("series");
uncountable("fish");
uncountable("sheep");
uncountable("jeans");
/**
* Returns the plural form of the word in the string.
*/
exports.pluralize = function (word) {
var wlc = word.toLowerCase();
for (var i = 0; i < UNCOUNTABLES.length; i++) {
var uncountable = UNCOUNTABLES[i];
if (wlc == uncountable) {
return word;
}
}
for (var i = 0; i < PLURALS.length; i++) {
var rule = PLURALS[i][0],
replacement = PLURALS[i][1];
if (rule.test(word)) {
return word.replace(rule, replacement);
}
}
}
/**
* Returns the singular form of the word in the string.
*/
exports.singularize = function (word) {
var wlc = word.toLowerCase();
for (var i = 0; i < UNCOUNTABLES.length; i++) {
var uncountable = UNCOUNTABLES[i];
if (wlc == uncountable) {
return word;
}
}
for (var i = 0; i < SINGULARS.length; i++) {
var rule = SINGULARS[i][0],
replacement = SINGULARS[i][1];
if (rule.test(word)) {
return word.replace(rule, replacement);
}
}
return word
}
/**
* Capitalizes the first word and turns underscores into spaces and strips a
* trailing "Key", if any. Like +titleize+, this is meant for creating pretty
* output.
*
* Examples:
* "employeeSalary" => "employee salary"
* "authorKey" => "author"
*/
exports.humanize = function (word) {
for (var i = 0; i < HUMANS.length; i++) {
var rule = HUMANS[i][0],
replacement = HUMANS[i][1];
if (rule.test(word)) {
word = word.replace(rule, replacement);
}
}
return exports.split(word, " ").toLowerCase();
}
/**
* Split a camel case word in its terms.
*/
exports.split = function (word, delim) {
delim = delim || " ";
var replacement = "$1" + delim + "$2";
return word.
replace(/([A-Z]+)([A-Z][a-z])/g, replacement).
replace(/([a-z\d])([A-Z])/g, replacement);
}
/**
* Converts a CamelCase word to underscore format.
*/
exports.underscore = function (word) {
return exports.split(word, "_").toLowerCase();
}
/**
* Converts a CamelCase word to dash (lisp style) format.
*/
exports.dash = exports.dasherize = function (word) {
return exports.split(word, "-").toLowerCase();
}
/*
Defines Mixin for all models.
*/
var Associations = module.exports = {
classMethods: {
hasOne: function(associationName, associatedModel, options) {
},
hasMany: function(associationName, associatedModel, options) {
},
belongsTo: function(associationName, associatedModel, options) {
}
},
instanceMethods: {
}
}
\ No newline at end of file
module.exports.Factory = function(Sequelize, sequelize) {
var Factory = {
addManyToManyMethods: function(table1, table2, assocName, backAssocName) {
table1.prototype[Sequelize.Helper.SQL.addPrefix('get', assocName)] = Factory.createManyToManyGetter(table1, table2, assocName, backAssocName)
table1.prototype[Sequelize.Helper.SQL.addPrefix('set', assocName)] = Factory.createManyToManySetter(table1, table2, assocName, backAssocName)
},
addOneToManyMethods: function(table1, table2, assocName, methodName) {
var setterName = Sequelize.Helper.SQL.addPrefix('set', methodName || assocName),
getterName = Sequelize.Helper.SQL.addPrefix('get', methodName || assocName)
table1.prototype[setterName] = Factory.createOneToManySetter(table1, assocName, methodName)
table1.prototype[getterName] = Factory.createOneToManyGetter(table1, table2, assocName, methodName)
},
addOneToOneMethods: function(table1, table2, assocName, backAssocName) {
var setterName = Sequelize.Helper.SQL.addPrefix('set', backAssocName || assocName, true),
getterName = Sequelize.Helper.SQL.addPrefix('get', backAssocName || assocName, true)
// getter
table1.prototype[getterName] = function(callback) {
var whereConditions = {}
whereConditions[Sequelize.Helper.SQL.asTableIdentifier(assocName)] = this.id
table2.find(whereConditions, callback)
}
// setter
table1.prototype[setterName] = function(object, callback) {
var self = this
this[Sequelize.Helper.SQL.addPrefix('get', backAssocName, true)](function(currentAssociation) {
var attr = {}
if(currentAssociation == null) {
attr[Sequelize.Helper.SQL.asTableIdentifier(assocName)] = self.id
object.updateAttributes(attr, callback)
} else {
if(object.id == currentAssociation.id) callback(currentAssociation)
else {
// first update the currently associated item to have no association any more
attr[Sequelize.Helper.SQL.asTableIdentifier(assocName)] = null
currentAssociation.updateAttributes(attr, function() {
// now update the object itself to set the new association
attr[Sequelize.Helper.SQL.asTableIdentifier(assocName)] = self.id
object.updateAttributes(attr, callback)
})
}
}
})
}
},
createManyToManyGetter: function(table1, table2, assocName, backAssocName) {
return function(options, callback) {
var _callback = ((typeof options == 'object') ? callback : options),
_options = (typeof options == 'object') ? options : {},
self = this
if(_options.force || !this.hasFetchedAssociationFor(assocName)) {
var Association = sequelize.tables[Sequelize.Helper.SQL.manyToManyTableName(assocName, backAssocName)].klass,
assocNameAsTableIdentifier = Sequelize.Helper.SQL.asTableIdentifier(backAssocName),
whereConditions = ['`'+assocNameAsTableIdentifier+'`', this.id].join("=")
Association.findAll({ where: whereConditions }, function(result) {
if(result.length > 0) {
var ids = Sequelize.Helper.Array.map(result, function(resultSet) {
return resultSet[Sequelize.Helper.SQL.asTableIdentifier(assocName)]
})
table2.findAll({where: "`id` IN (" + ids.join(",") + ")"}, function(objects) {
self.setAssociationDataFor(assocName, objects)
if(_callback) _callback(objects)
})
} else {
if(_callback) _callback([])
}
})
} else {
if(_callback) _callback(this.getAssociationDataFor(assocName))
}
}
},
createManyToManySetter: function(table1, table2, assocName, backAssocName) {
return function(objects, callback) {
var self = this,
Association = sequelize.tables[Sequelize.Helper.SQL.manyToManyTableName(assocName, backAssocName)].klass,
objectIds = Sequelize.Helper.Array.map(objects, function(obj) { return obj.id })
var getAssociatedObjects = function(callback) {
self[Sequelize.Helper.SQL.addPrefix('get', assocName)]({refetchAssociations: true}, callback)
}
var deleteObsoleteAssociations = function(currentAssociations, callback) {
var obsoleteAssociations = Sequelize.Helper.Array.select(currentAssociations, function(assoc) { return objectIds.indexOf(assoc.id) == -1 }),
obsoleteIds = Sequelize.Helper.Array.map(obsoleteAssociations, function(assoc) { return assoc.id })
if(obsoleteIds.length == 0)
callback([])
else {
var deleteOptions = {
table: Association.tableName,
where:
"`" + Sequelize.Helper.SQL.asTableIdentifier(assocName) + "` IN (" + obsoleteIds.join(",") + ") AND " +
"`" + Sequelize.Helper.SQL.asTableIdentifier(backAssocName) + "` = " + self.id,
limit: null
}
sequelize.query( Sequelize.sqlQueryFor('delete', deleteOptions), function(){ callback(obsoleteIds) } )
}
}
var createNewAssociations = function(currentAssociations, obsoleteIds) {
var currentIds = Sequelize.Helper.Array.map(currentAssociations, function(assoc) { return assoc.id }),
withoutExisting = Sequelize.Helper.Array.select(objects, function(o) { return currentIds.indexOf(o.id) == -1 }),
savings = []
withoutExisting.forEach(function(o) {
if((o instanceof table2) && (self.id != null) && (o.id != null)) {
var attributes = {}
attributes[Sequelize.Helper.SQL.asTableIdentifier(backAssocName)] = self.id
attributes[Sequelize.Helper.SQL.asTableIdentifier(assocName)] = o.id
savings.push({save: new Association(attributes)})
}
})
Sequelize.chainQueries(savings, function() {
getAssociatedObjects(callback)
})
}
getAssociatedObjects(function(associatedObjects) {
deleteObsoleteAssociations(associatedObjects, function(obsolete) {
createNewAssociations(associatedObjects, obsolete)
})
})
}
},
createOneToManyGetter: function(table1, table2, assocName, methodName) {
return function(options, callback) {
var _callback = ((typeof options == 'object') ? callback : options),
_options = (typeof options == 'object') ? options : {},
accessKey = methodName || assocName,
self = this
if(_options.refetchAssociations || !this.hasFetchedAssociationFor(accessKey)) {
var whereConditions = ['`'+Sequelize.Helper.SQL.asTableIdentifier(assocName)+'`', this.id].join("=")
table2.findAll({where: whereConditions}, function(result) {
self.setAssociationDataFor(accessKey, result)
if(_callback) _callback(result)
})
} else {
var result = self.getAssociationDataFor(accessKey)
if(_callback) _callback(result)
}
}
},
createOneToManySetter: function(table1, assocName, methodName) {
return function(objects, callback) {
var self = this,
objectIds = Sequelize.Helper.Array.map(objects, function(obj) { return obj.id }),
getterName = Sequelize.Helper.SQL.addPrefix('get', methodName)
this[getterName]({refetchAssociations: true}, function(currentAssociations) {
var currentIds = Sequelize.Helper.Array.map(currentAssociations, function(assoc) { return assoc.id }),
obsoleteAssociations = Sequelize.Helper.Array.select(currentAssociations, function(assoc) { return objectIds.indexOf(assoc.id) == -1 }),
queries = []
obsoleteAssociations.forEach(function(assoc) {
var attr = {}
attr[Sequelize.Helper.SQL.asTableIdentifier(assocName)] = null
queries.push({updateAttributes: assoc, params: [attr]})
})
var newAssociations = Sequelize.Helper.Array.select(objects, function(o) { return currentIds.indexOf(o.id) == -1 })
newAssociations.forEach(function(assoc) {
var attr = {}
attr[Sequelize.Helper.SQL.asTableIdentifier(assocName)] = self.id
queries.push({updateAttributes: assoc, params: [attr]})
})
Sequelize.chainQueries(queries, function() {
self[getterName]({refetchAssociations: true}, callback)
})
})
}
}
}
return Factory
}
\ No newline at end of file
var Helper = function(Sequelize) {
this.Sequelize = Sequelize
this.Inflection = require(__dirname + "/../inflection/inflection")
this.QueryChainer = new (require("./Helper/QueryChainer").QueryChainer)(this)
this.options = {}
require(__dirname + "/Helper/Basics.js")(this)
require(__dirname + "/Helper/SQL.js")(this)
require(__dirname + "/Helper/Hash.js")(this)
require(__dirname + "/Helper/Array.js")(this)
}
exports.Helper = Helper
\ No newline at end of file
module.exports = function(instance) {
instance.Array = {
map: function(array, func) {
var result = []
array.forEach(function(element) {
result.push(func(element))
})
return result
},
reject: function(array, func) {
var result = []
array.forEach(function(element) {
if(!func(element)) result.push(element)
})
return result
},
select: function(array, func) {
var result = []
array.forEach(function(element) {
if(func(element)) result.push(element)
})
return result
},
without: function(array, withouts) {
var result = []
array.forEach(function(e) {
if(withouts.indexOf(e) == -1) result.push(e)
})
return result
},
join: function(arr1, arr2) {
var result = []
arr1.forEach(function(e) { result.push(e) })
arr2.forEach(function(e) { result.push(e) })
return result
}
}
}
\ No newline at end of file
module.exports = function(instance) {
instance.configure = function(options) {
this.options = options
}
instance.log = function(obj) {
var sys = require("sys")
sys.log(sys.inspect(obj))
}
instance.evaluateTemplate = function(template, replacements) {
var result = template
this.Hash.keys(replacements).forEach(function(key) {
result = result.replace("%{" + key + "}", replacements[key])
})
return result
}
}
\ No newline at end of file
module.exports = function(instance) {
instance.Hash = {
isHash: function(obj) {
return (typeof obj == 'object') && !obj.hasOwnProperty('length')
},
forEach: function(object, func) {
instance.Hash.keys(object).forEach(function(key) {
func(object[key], key, object)
})
},
map: function(object, func) {
var result = []
instance.Hash.forEach(object, function(value, key, object) {
result.push(func(value, key, object))
})
return result
},
keys: function(object) {
var results = []
for (var property in object)
results.push(property)
return results
},
values: function(object) {
var result = []
instance.Hash.keys(object).forEach(function(key) {
result.push(object[key])
})
return result
},
merge: function(source, target, force) {
instance.Hash.forEach(source, function(value, key) {
if(!target[key] || force)
target[key] = value
})
return target
},
without: function(object, withoutKeys) {
var result = {}
instance.Hash.forEach(object, function(value, key) {
if(withoutKeys.indexOf(key) == -1)
result[key] = value
})
return result
}
}
}
\ No newline at end of file
var sys = require("sys")
var QueryChainer = function(Helper) {
this.Helper = Helper
}
var instanceMethods = {
splitQueryHash: function(queryHash) {
var method = this.Helper.Array.without(this.Helper.Hash.keys(queryHash), "params")[0],
object = queryHash[method]
return { method: method, object: object }
},
splitArguments: function() {
var result = { queries: [], callback: null }
for(var i = 0; i < arguments.length; i++) {
var arg = arguments[i]
if(typeof arg == 'function') result.callback = arg
else if(Array.isArray(arg)) arg.forEach(function(o) { result.queries.push(o) })
else result.queries.push(arg)
}
return result
},
expandMultiQueries: function(queries) {
var self = this,
result = [],
multiQueries = []
queries.forEach(function(queryHash) {
var splittedQueryHash = self.splitQueryHash(queryHash),
method = splittedQueryHash.method,
object = splittedQueryHash.object
if(!Array.isArray(object))
result.push(queryHash)
else if(object.length > 0) {
for(var i = 0; i < object.length; i++) {
var newQueryHash = { params: queryHash.params }
newQueryHash[method] = object[i]
result.push(newQueryHash)
}
}
})
return result
},
executeQuery: function(queries, index, callback) {
var self = this,
queryHash = queries[index],
splittedQueryHash = this.splitQueryHash(queryHash),
method = splittedQueryHash.method,
object = splittedQueryHash.object
var iterator = function() {
if(queries.length > (index + 1)) self.executeQuery(queries, index + 1, callback)
else if (callback) callback()
}
object[method].apply(object, this.Helper.Array.join(queryHash.params || [], [iterator]))
},
chain: function() {
var self = this
var args = this.splitArguments.apply(this, arguments),
queries = args.queries,
callback = args.callback
var expandedQueries = this.expandMultiQueries(queries)
if(queries.length > 0) this.executeQuery(expandedQueries, 0, callback)
else callback && callback()
}
}
for(var methodName in instanceMethods)
QueryChainer.prototype[methodName] = instanceMethods[methodName]
module.exports.QueryChainer = QueryChainer
\ No newline at end of file
module.exports = function(instance) {
instance.SQL = {
isManyToManyAssociation: function(association) {
return (['hasMany', 'hasAndBelongsToMany'].indexOf(association.type) > -1)
},
manyToManyTableName: function(name1, name2) {
var _name1 = name1[0].toUpperCase() + name1.replace(/^./, "")
var _name2 = name2[0].toUpperCase() + name2.replace(/^./, "")
return [_name1, _name2].sort().join("")
},
asTableIdentifier: function(name) {
var _name = name[0].toLowerCase() + name.replace(/^./, "")
return instance.Inflection.singularize(_name) + "Id"
},
addPrefix: function(prefix, string, singularize) {
var _string = singularize ? instance.Inflection.singularize(string) : instance.Inflection.pluralize(string)
return prefix + _string[0].toUpperCase() + _string.replace(/^./, "")
},
asTableName: function(name) {
return instance.options.disableTableNameModification
? name
: instance.Inflection.pluralize(name)
},
asSqlDate: function(date) {
return [
[
date.getFullYear(),
((date.getMonth() < 9 ? '0' : '') + (date.getMonth()+1)),
((date.getDate() < 10 ? '0' : '') + date.getDate())
].join("-"),
date.toLocaleTimeString()
].join(" ")
},
valuesForInsertQuery: function(object) {
var actualValues = object.values,
result = []
instance.Hash.forEach(actualValues, function(value, key) {
var dataType = object.table.attributes[key]
result.push(instance.SQL.transformValueByDataType(value, dataType))
})
return result
},
valuesForUpdate: function(object, options) {
var actualValues = object.values,
result = [],
self = instance
options = options || {}
instance.Hash.forEach(actualValues, function(value, key) {
var dataType = object.table.attributes[key],
_key = ['', key, ''].join('`')
result.push([_key, self.SQL.transformValueByDataType(value, dataType)].join(" = "))
})
return result.join(options.seperator || ", ")
},
fieldsForInsertQuery: function(object) {
return instance.Hash.keys(object.values).map(function(value) {
return ['', value, ''].join('`')
}).join(", ")
},
transformValueByDataType: function(value, attributeOptions) {
var dataType = attributeOptions.type
if((value == null)||(typeof value == 'undefined')||((dataType.indexOf(instance.Sequelize.INTEGER) > -1) && isNaN(value)))
return "NULL"
if(dataType.indexOf(instance.Sequelize.FLOAT) > -1)
return (typeof value == 'number') ? value : parseFloat(value.replace(",", "."))
if(dataType.indexOf(instance.Sequelize.BOOLEAN) > -1)
return (value === true ? 1 : 0)
if(dataType.indexOf(instance.Sequelize.INTEGER) > -1)
return value
if(dataType.indexOf(instance.Sequelize.DATE) > -1)
return ("'" + instance.SQL.asSqlDate(value) + "'")
return ("'" + value + "'")
},
getDataTypeForValue: function(value) {
switch(typeof value) {
case 'number':
return (value.toString().indexOf('.') > -1) ? instance.Sequelize.FLOAT : instance.Sequelize.INTEGER
break
case 'boolean':
return instance.Sequelize.BOOLEAN
break
case 'object':
return (value.getMilliseconds) ? instance.Sequelize.DATE : "WTF!"
break
default:
return instance.Sequelize.TEXT
break
}
},
hashToWhereConditions: function(conditions, attributes) {
attributes = attributes || {}
if(typeof conditions == 'number')
return ('`id`=' + conditions)
else {
return instance.Hash.map(conditions, function(value, key) {
var dataType = attributes[key] || {type:instance.SQL.getDataTypeForValue(value)},
_value = instance.SQL.transformValueByDataType(value, dataType),
_key = ['', key, ''].join('`')
if(_value == 'NULL')
return _key + " IS NULL"
else
return [_key, _value].join("=")
}).join(" AND ")
}
}
}
}
\ No newline at end of file
var Sequelize = function(database, username, password, options) {
options = options || {}
this.tables = {}
this.options = Sequelize.Helper.Hash.without(options, ["host", "port", "disableTableNameModification"])
this.config = {
database: database,
username: username,
password: (((["", null, false].indexOf(password) > -1) || (typeof password == 'undefined')) ? null : password),
host : options.host || 'localhost',
port : options.port || 3306
}
Sequelize.Helper.configure({
disableTableNameModification: (options.disableTableNameModification || false)
})
}
var classMethods = {
Helper: new (require(__dirname + "/Helper").Helper)(Sequelize),
STRING: 'VARCHAR(255)',
TEXT: 'TEXT',
INTEGER: 'INT',
DATE: 'DATETIME',
BOOLEAN: 'TINYINT(1)',
FLOAT: 'FLOAT',
sqlQueryFor: function(command, values) {
var query = null
if(values.hasOwnProperty('fields') && Array.isArray(values.fields))
values.fields = values.fields.map(function(field) { return ['', field, ''].join('`') }).join(", ")
switch(command) {
case 'create':
query = "CREATE TABLE IF NOT EXISTS `%{table}` (%{fields})"
break
case 'drop':
query = "DROP TABLE IF EXISTS `%{table}`"
break
case 'select':
values.fields = values.fields || '*'
query = "SELECT %{fields} FROM `%{table}`"
if(values.where) {
if(Sequelize.Helper.Hash.isHash(values.where))
values.where = Sequelize.Helper.SQL.hashToWhereConditions(values.where)
query += " WHERE %{where}"
}
if(values.order) query += " ORDER BY %{order}"
if(values.group) query += " GROUP BY %{group}"
if(values.limit) {
if(values.offset) query += " LIMIT %{offset}, %{limit}"
else query += " LIMIT %{limit}"
}
break
case 'insert':
query = "INSERT INTO `%{table}` (%{fields}) VALUES (%{values})"
break
case 'update':
if(Sequelize.Helper.Hash.isHash(values.values))
values.values = Sequelize.Helper.SQL.hashToWhereConditions(values.values)
query = "UPDATE `%{table}` SET %{values} WHERE `id`=%{id}"
break
case 'delete':
if(Sequelize.Helper.Hash.isHash(values.where))
values.where = Sequelize.Helper.SQL.hashToWhereConditions(values.where)
query = "DELETE FROM `%{table}` WHERE %{where}"
if(typeof values.limit == 'undefined') query += " LIMIT 1"
else if(values.limit != null) query += " LIMIT " + values.limit
break
}
return Sequelize.Helper.evaluateTemplate(query, values)
},
chainQueries: function() {
this.Helper.QueryChainer.chain.apply(this.Helper.QueryChainer, arguments)
}
}
Sequelize.prototype = {
define: function(name, attributes, options) {
var SequelizeTable = require(__dirname + "/SequelizeTable").SequelizeTable
var _attributes = {}
var createdAt = "createdAt";
var updatedAt = "updatedAt";
if(options){
if(options.createdAt)createdAt = options.createdAt;
if(options.updatedAt)updatedAt = options.updatedAt;
}
Sequelize.Helper.Hash.forEach(attributes, function(value, key) {
if(typeof value == 'string')
_attributes[key] = { type: value }
else if((typeof value == 'object') && (!value.length))
_attributes[key] = value
else
throw new Error("Please specify a datatype either by using Sequelize.* or pass a hash!")
})
_attributes[createdAt] = { type: Sequelize.DATE, allowNull: false}
_attributes[updatedAt] = { type: Sequelize.DATE, allowNull: false}
var table = new SequelizeTable(Sequelize, this, Sequelize.Helper.SQL.asTableName(name), _attributes, options)
// refactor this to use the table's attributes
this.tables[name] = {klass: table, attributes: attributes}
table.sequelize = this
return table
},
import: function(path) {
var imported = require(path),
self = this,
result = {}
Sequelize.Helper.Hash.forEach(imported, function(definition, functionName) {
definition(Sequelize, self)
})
Sequelize.Helper.Hash.forEach(this.tables, function(constructor, name) {
result[name] = constructor.klass
})
return result
},
get tableNames() {
var result = []
Sequelize.Helper.Hash.keys(this.tables).forEach(function(tableName) {
result.push(Sequelize.Helper.SQL.asTableName(tableName))
})
return result
},
sync: function(callback) {
var finished = [],
tables = this.tables,
errors = []
Sequelize.Helper.Hash.forEach(tables, function(table) {
table.klass.prepareAssociations()
})
if((Sequelize.Helper.Hash.keys(this.tables).length == 0) && callback)
callback()
else
Sequelize.Helper.Hash.forEach(tables, function(table) {
table.klass.sync(function(_, err) {
finished.push(true)
if(err) errors.push(err)
if((finished.length == Sequelize.Helper.Hash.keys(tables).length) && callback)
callback(errors)
})
})
},
drop: function(callback) {
var finished = [],
tables = this.tables,
errors = []
if((Sequelize.Helper.Hash.keys(tables).length == 0) && callback)
callback()
else
Sequelize.Helper.Hash.forEach(tables, function(table, tableName) {
table.klass.drop(function(_, err) {
finished.push(true)
if(err) errors.push(err)
if((finished.length == Sequelize.Helper.Hash.keys(tables).length) && callback)
callback(errors)
})
})
},
query: function(queryString, callback) {
var fields = [],
values = [],
self = this,
client = require(__dirname + "/../nodejs-mysql-native/index").createTCPClient(this.config.host, this.config.port)
client.connection.on('error', function() {
callback(null, null, { message: "Unable to establish a connection to " + [self.config.host, self.config.port].join(":") })
})
client.auto_prepare = true
client
.auth(self.config.database, self.config.username, self.config.password)
.on('error', function(err) { callback(null, null, err) })
.on('authorized', function() {
if(!self.options.disableLogging)
Sequelize.Helper.log("Executing the query: " + queryString)
client
.query(queryString)
.on('error', function(err) { Sequelize.Helper.log(err) })
.on('row', function(r){ values.push(r) })
.on('field', function(f){ fields.push(f)})
.on('end', function(stats) {
if(callback) {
var result = []
values.forEach(function(valueArray) {
var mapping = {}
for(var i = 0; i < fields.length; i++)
mapping[fields[i].name] = valueArray[i]
result.push(mapping)
})
if(callback) callback(result, stats)
}
})
client.close()
})
}
}
for (var key in classMethods) Sequelize[key] = classMethods[key]
module.exports = Sequelize
\ No newline at end of file
/*
A.hasOne(B) => B.aId
A.belongsTo(B) => A.bId
A.hasMany(B) => B.aId
A.hasMany(B) + B.hasMany(A) => AB.aId + AB.bId
*/
exports.SequelizeTable = function(Sequelize, sequelize, tableName, attributes, options) {
options = options || {}
options.classMethods = options.classMethods || {}
options.instanceMethods = options.instanceMethods || {}
//for dinamic timestamp field names
var createdAt = "createdAt";
var updatedAt = "updatedAt";
if(options.createdAt)createdAt = options.createdAt;
if(options.updatedAt)updatedAt = options.updatedAt;
var table = function(values) {
var self = this,
defaults = {}
// read all default values ...
Sequelize.Helper.Hash.forEach(table.attributes, function(options, key) {
if(typeof options.default != 'undefined') defaults[key] = options.default
})
// and merge them into the passed one
Sequelize.Helper.Hash.merge(defaults, values)
// now iterate over the values and assign them the current object
Sequelize.Helper.Hash.forEach(values, function(value, key) {
if(attributes[key]) {
if(attributes[key].type.indexOf(Sequelize.BOOLEAN) > -1)
self[key] = ((value == 1) || (value == true)) ? true : false
else if(attributes[key].type.indexOf(Sequelize.DATE) > -1)
self[key] = (value instanceof Date) ? value : new Date(Date.parse(value))
else
self[key] = value
}
})
this.id = null // specify id as null to declare this object as unsaved and as not present in the database
this.table = table
this.fetchedAssociations = {}
}
// class methods
var classMethods = {
associations: [],
attributes: attributes,
tableName: tableName,
prepareAssociations: function(callback) {
table.associations.forEach(function(association) {
var assocNameAsTableIdentifier = Sequelize.Helper.SQL.asTableIdentifier(association.name)
switch(association.type) {
case 'hasMany':
if(association.backAssociationName) {
// many to many relation
var _attributes = {}
_attributes[assocNameAsTableIdentifier] = Sequelize.INTEGER
_attributes[Sequelize.Helper.SQL.asTableIdentifier(association.backAssociationName)] = Sequelize.INTEGER
sequelize.define(Sequelize.Helper.SQL.manyToManyTableName(association.name, association.backAssociationName), _attributes)
} else {
// one to many relation
association.table.attributes[assocNameAsTableIdentifier] = {type: Sequelize.INTEGER}
}
break
case 'hasAndBelongsToMany':
var _attributes = {}
_attributes[assocNameAsTableIdentifier] = Sequelize.INTEGER
_attributes[Sequelize.Helper.SQL.asTableIdentifier(association.table.tableName)] = Sequelize.INTEGER
sequelize.define(Sequelize.Helper.SQL.manyToManyTableName(association.name, association.table.tableName), _attributes)
break
case 'hasOne':
// adds the foreign key to the associated table
// e.g. assocTable.myTableId = Sequelize.INTEGER
association.table.attributes[assocNameAsTableIdentifier] = {type: Sequelize.INTEGER}
break
case 'belongsTo':
// adds the foreign key to me
// e.g. table.dayId = Sequelize.INTEGER
table.attributes[assocNameAsTableIdentifier] = {type: Sequelize.INTEGER}
break
}
})
if(callback) callback()
},
/* returns: table, error */
sync: function(callback) {
var fields = ["`id` INT NOT NULL auto_increment PRIMARY KEY"]
Sequelize.Helper.Hash.forEach(table.attributes, function(options, name) {
fields.push('`' + name + "` " + options.type)
})
sequelize.query(
Sequelize.sqlQueryFor( 'create', { table: table.tableName, fields: fields.join(', ') } ),
function(_, _, err) { if(callback) callback(table, err) }
)
},
drop: function(callback) {
sequelize.query(
Sequelize.sqlQueryFor('drop', { table: table.tableName }),
function(_, _, err) { if(callback) callback(table, err) }
)
},
findAll: function(options, callback) {
// use the first param as callback if it is no object (hash)
var _callback = ((typeof options == 'function') ? options : callback)
var queryOptions = (typeof options == 'object')
? Sequelize.Helper.Hash.merge(options, { table: table.tableName })
: { table: table.tableName }
sequelize.query(
Sequelize.sqlQueryFor('select', queryOptions),
function(result) {
var objects = result.map(function(r) { return table.sqlResultToObject(r) })
if(queryOptions.fetchAssociations) {
var fetchings = []
objects.map(function(object) { fetchings.push({fetchAssociations: object}) })
Sequelize.chainQueries(fetchings, function() {
if(_callback) _callback(objects)
})
} else {
if(_callback) _callback(objects)
}
}
)
},
find: function(conditions, options, callback) {
// use the second param as callback if it is no object (hash)
var _callback = ((typeof options == 'object') ? callback : options)
sequelize.query(
Sequelize.sqlQueryFor('select', {
table: table.tableName,
where: Sequelize.Helper.SQL.hashToWhereConditions(conditions, table.attributes),
order: '`id` DESC',
limit: 1
}), function(result) {
var _result = result[0] ? table.sqlResultToObject(result[0]) : null
if(options.fetchAssociations && (_result != null))
_result.fetchAssociations(function() { if (_callback) _callback(_result) })
else
if (_callback) _callback(_result)
}
)
},
sqlResultToObject: function(result) {
if(typeof result == undefined) return null
var object = new table(result)
object.id = result.id
return object
},
hasAndBelongsToMany: function(assocName) {
if(typeof assocName == 'undefined')
throw new Error('Please specify at least an association name!')
var association = { name: assocName, table: table, type: 'hasAndBelongsToMany' },
Factory = new require("./Factory").Factory(Sequelize, sequelize)
table.associations.push(association)
table.prototype[Sequelize.Helper.SQL.addPrefix('get', assocName)] = Factory.createManyToManyGetter(null, table, assocName, table.tableName)
table.prototype[Sequelize.Helper.SQL.addPrefix('set', assocName)] = Factory.createManyToManySetter(table, table, assocName, table.tableName)
return association
},
hasMany: function(assocName, associationTable, backAssocName) {
if(typeof assocName == 'undefined')
throw new Error('Please specify at least an association name!')
if(associationTable) {
var Factory = new require("./Factory").Factory(Sequelize, sequelize),
association = { name: assocName, backAssociationName: backAssocName, table: associationTable, type: 'hasMany' },
backAssociation = { name: backAssocName, backAssociationName: assocName, table: table, type: 'hasMany' }
table.associations.push(association)
if(backAssocName) {
associationTable.associations.push(backAssociation)
Factory.addManyToManyMethods(table, associationTable, assocName, backAssocName)
Factory.addManyToManyMethods(associationTable, table, backAssocName, assocName)
} else {
Factory.addOneToManyMethods(table, associationTable, assocName)
}
return association
} else {
return this.hasAndBelongsToMany(assocName)
}
},
hasManyAndBelongsTo: function(assocName, _table, backAssocName) {
var assoc = table.hasMany(assocName, _table)
_table.belongsTo(backAssocName || assocName, table, assoc)
},
hasOne: function(assocName, _table) {
var Factory = new require("./Factory").Factory(Sequelize, sequelize),
association = { name: assocName, table: _table, type: 'hasOne' }
table.associations.push(association)
Factory.addOneToOneMethods(table, _table, assocName)
return association
},
hasOneAndBelongsTo: function(assocName, _table, backAssocName) {
var assoc = table.hasOne(assocName, _table)
_table.belongsTo(backAssocName || assocName, table, assoc)
},
belongsTo: function(assocName, _table, backAssociation) {
if(typeof backAssociation == 'undefined')
throw new Error("Calling belongsTo with only two parameters is deprecated! Please take a look at the example in the repository!")
// start - overwrite the association of the before defined hasOne or hasMany relation, to fit the belongsTo foreign keys
var Factory = new require("./Factory").Factory(Sequelize, sequelize),
isManyToManyAssociation = Sequelize.Helper.SQL.isManyToManyAssociation(backAssociation)
delete _table.prototype[Sequelize.Helper.SQL.addPrefix('get', backAssociation.name, !isManyToManyAssociation)]
delete _table.prototype[Sequelize.Helper.SQL.addPrefix('set', backAssociation.name, !isManyToManyAssociation)]
if(backAssociation.type == 'hasMany')
Factory.addOneToManyMethods(_table, table, assocName, backAssociation.name)
else
Factory.addOneToOneMethods(_table, table, assocName, backAssociation.name)
// TODO: check if the following line is not needed; specs r failing
// backAssociation.name = assocName
// end - overwrite the association of the before defined hasOne or hasMany relation, to fit the belongsTo foreign keys
table.associations.push({ name: assocName, table: _table, type: 'belongsTo' })
// getter
table.prototype[Sequelize.Helper.SQL.addPrefix('get', assocName, true)] = function(callback) {
var identifier = Sequelize.Helper.SQL.asTableIdentifier(assocName)
if((this[identifier] == null)||(isNaN(this[identifier]))) callback([])
else _table.find(this[identifier], callback)
}
// setter
table.prototype[Sequelize.Helper.SQL.addPrefix('set', assocName, true)] = function(object, callback) {
var self = this,
attr = {}
attr[Sequelize.Helper.SQL.asTableIdentifier(assocName)] = object.id
this.updateAttributes(attr, function() {
self[Sequelize.Helper.SQL.addPrefix('get', assocName, true)](callback)
})
}
return _table
},
count: function(conditions, callback) {
var _callback = (typeof conditions == 'function') ? conditions : callback
, options = {fields: "count(id)", table: table.tableName}
if (typeof conditions != 'function')
options.where = conditions
sequelize.query(Sequelize.sqlQueryFor("select", options), function(result) {
_callback && _callback(result[0]["count(id)"])
})
}
}
// don't put this into the hash!
classMethods.identifier = Sequelize.Helper.SQL.asTableIdentifier(classMethods.tableName)
// instance methods
table.prototype = {
get values() {
var result = {}
var self = this
Sequelize.Helper.Hash.keys(table.attributes).forEach(function(attribute) {
result[attribute] = (typeof self[attribute] == "undefined") ? null : self[attribute]
})
return result
},
get invalidFields() {
var result = [],
self = this
Sequelize.Helper.Hash.forEach(table.attributes, function(options, attribute) {
if([createdAt, updatedAt].indexOf(attribute) > -1) return
var allowsNull = ((typeof options.allowNull == 'undefined') || (options.allowNull !== false))
var hasDefault = (typeof options.default != 'undefined')
if(!allowsNull && !hasDefault && (typeof self[attribute] == 'undefined'))
result.push({ field: attribute, reason: 'The field does not allow NULL values and has no default!'})
})
return result
},
get isValid() {
return this.invalidFields.length == 0
},
get isNewRecord() {
return this.id == null
},
fetchAssociations: function(callback) {
var associatedData = {},
self = this,
setAssociatedDataAndReturn = function() {
self.fetchedAssociations = associatedData
if(callback) callback(self.fetchedAssociations)
}
if(this.table.associations.length == 0)
setAssociatedDataAndReturn()
else
this.table.associations.forEach(function(association) {
var isManyToManyAssociation = Sequelize.Helper.SQL.isManyToManyAssociation(association),
getter = Sequelize.Helper.SQL.addPrefix('get', association.name, !isManyToManyAssociation)
self[getter](function(objects) {
associatedData[association.name] = objects
if(Sequelize.Helper.Hash.keys(associatedData).length == self.table.associations.length)
setAssociatedDataAndReturn()
})
})
},
hasFetchedAssociationFor: function(assocName) {
return (this.fetchedAssociations && this.fetchedAssociations[assocName])
},
setAssociationDataFor: function(assocName, data) {
this.fetchedAssociations[assocName] = data
},
getAssociationDataFor: function(assocName) {
return this.fetchedAssociations[assocName]
},
save: function(callback) {
var query = null,
self = this
if(!this.isValid) {
var errorText = "The object is not valid! Invalid fields: " + Sequelize.Helper.Array.map(this.invalidFields, function(fieldHash) { return fieldHash.field }).join(", ")
throw new Error(errorText)
}
this[updatedAt] = new Date()
if(this.isNewRecord) {
this[createdAt] = new Date()
query = Sequelize.sqlQueryFor('insert', {
table: table.tableName,
fields: Sequelize.Helper.SQL.fieldsForInsertQuery(this),
values: Sequelize.Helper.SQL.valuesForInsertQuery(this)
})
} else {
query = Sequelize.sqlQueryFor('update', { table: table.tableName, values: Sequelize.Helper.SQL.valuesForUpdate(this), id: this.id })
}
sequelize.query(query, function(result, stats) {
self.id = self.id || stats.insert_id
if(callback) callback(self)
})
},
updateAttributes: function(newValues, callback) {
var self = this
Sequelize.Helper.Hash.keys(table.attributes).forEach(function(attribute) {
if(typeof newValues[attribute] != 'undefined')
self[attribute] = newValues[attribute]
})
this.save(callback)
},
destroy: function(callback) {
sequelize.query(
Sequelize.sqlQueryFor('delete', { table: table.tableName, where: ['id', this.id].join("=") }),
callback
)
}
}
// merge classMethods + passed classMethods
Sequelize.Helper.Hash.merge(options.classMethods, classMethods)
Sequelize.Helper.Hash.forEach(classMethods, function(method, methodName) {
table[methodName] = method
})
// merge passed instanceMethods
Sequelize.Helper.Hash.forEach(options.instanceMethods, function(method, methodName) {
table.prototype[methodName] = method
})
return table
}
\ No newline at end of file
var config = require("./config")
, Sequelize = require("./../index")
, sequelize = new Sequelize(config.database, config.username, config.password)
var User = sequelize.define('User', {
name: Sequelize.STRING,
bio: Sequelize.TEXT
})
User.sync({force: true}).on('success', function() {
User
.create({name: 'barfooz', bio: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'})
.on('success', function(user) {
// User.findAll().on('success', function(users) {
// console.log('Found the following users', users.map(function(u) { return u.name }))
// })
User.find(user.id).on('success', function(_user) {
console.log('Found the following user', _user)
})
})
})
\ No newline at end of file
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!