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

Commit c7592d70 by Sascha Depold

added method for fetching associated data

1 parent f5c504a6
......@@ -14,6 +14,10 @@ exports.Helper = function(Sequelize) {
},
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(/^./, "")
......
......@@ -9,11 +9,11 @@ exports.SequelizeTable = function(Sequelize, sequelize, tableName, attributes, o
options = options || {}
options.classMethods = options.classMethods || {}
options.instanceMethods = options.instanceMethods || {}
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
......@@ -21,7 +21,7 @@ exports.SequelizeTable = function(Sequelize, sequelize, tableName, attributes, o
// 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]) {
......@@ -33,17 +33,17 @@ exports.SequelizeTable = function(Sequelize, sequelize, tableName, attributes, o
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
}
// 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)
......@@ -81,7 +81,7 @@ exports.SequelizeTable = function(Sequelize, sequelize, tableName, attributes, o
})
if(callback) callback()
},
/* returns: table, error */
sync: function(callback) {
var fields = ["id INT NOT NULL auto_increment PRIMARY KEY"]
......@@ -139,33 +139,33 @@ exports.SequelizeTable = function(Sequelize, sequelize, tableName, attributes, o
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)
......@@ -173,37 +173,37 @@ exports.SequelizeTable = function(Sequelize, sequelize, tableName, attributes, o
} 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)
......@@ -216,12 +216,13 @@ exports.SequelizeTable = function(Sequelize, sequelize, tableName, attributes, o
delete _table.prototype[Sequelize.Helper.SQL.addPrefix('set', backAssociation.name)]
Factory.addOneToOneMethods(_table, table, assocName, backAssociation.name)
}
backAssociation.name = assocName
// 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)
......@@ -229,25 +230,25 @@ exports.SequelizeTable = function(Sequelize, sequelize, tableName, attributes, o
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
}
}
// don't put this into the hash!
classMethods.identifier = Sequelize.Helper.SQL.asTableIdentifier(classMethods.tableName)
// instance methods
table.prototype = {
get values() {
......@@ -260,32 +261,55 @@ exports.SequelizeTable = function(Sequelize, sequelize, tableName, attributes, o
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
},
loadAssociatedData: function(callback) {
var associatedData = {},
self = this,
setAssociatedDataAndReturn = function() {
self.associatedData = associatedData
if(callback) callback(associatedData)
}
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()
})
})
},
save: function(callback) {
var query = null,
self = this
......@@ -298,7 +322,7 @@ exports.SequelizeTable = function(Sequelize, sequelize, tableName, attributes, o
this.updatedAt = new Date()
if(this.isNewRecord) {
this.createdAt = new Date()
query = Sequelize.sqlQueryFor('insert', {
table: table.tableName,
fields: Sequelize.Helper.SQL.fieldsForInsertQuery(this),
......@@ -307,13 +331,13 @@ exports.SequelizeTable = function(Sequelize, sequelize, tableName, attributes, o
} 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) {
......@@ -323,7 +347,7 @@ exports.SequelizeTable = function(Sequelize, sequelize, tableName, attributes, o
this.save(callback)
},
destroy: function(callback) {
sequelize.query(
Sequelize.sqlQueryFor('delete', { table: table.tableName, where: ['id', this.id].join("=") }),
......@@ -331,17 +355,17 @@ exports.SequelizeTable = function(Sequelize, sequelize, tableName, attributes, o
)
}
}
// merge classMethods + passed classMethods
Sequelize.Helper.Hash.merge(options.classMethods, classMethods)
Sequelize.Helper.Hash.forEach(classMethods, function(method, methodName) {
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
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!