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

Commit 803192aa by Sascha Depold

many-to-many connection is working. woot!

1 parent 832fa070
......@@ -17,7 +17,7 @@ var HasMany = module.exports = function(srcModel, targetModel, options) {
HasMany.prototype.injectAttributes = function() {
this.identifier = this.options.foreignKey || Utils._.underscoredIf(this.source.tableName + "Id", this.options.underscored)
if(this.target.associations.hasOwnProperty(this.source.tableName)) {
if (this.target.associations.hasOwnProperty(this.source.tableName)) {
// remove the obsolete association identifier from the source
this.foreignIdentifier = this.target.associations[this.source.tableName].identifier
delete this.source.attributes[this.foreignIdentifier]
......@@ -30,6 +30,8 @@ HasMany.prototype.injectAttributes = function() {
this.connectorModel =
this.target.associations[this.source.tableName].connectorModel =
this.source.modelManager.sequelize.define(Utils.combineTableNames(this.source.tableName, this.target.tableName), combinedTableAttributes)
this.connectorModel.sync()
} else {
var newAttributes = {}
newAttributes[this.identifier] = { type: DataTypes.INTEGER }
......@@ -43,13 +45,17 @@ HasMany.prototype.injectGetter = function(obj) {
var self = this
obj[this.accessors.get] = function() {
var instance = this
if(self.connectorModel) {
var customEventEmitter = new Utils.CustomEventEmitter(function() {
var where = {}
where[self.identifier] = instance.id
where[self.identifier] = this.id
self.connectorModel.findAll({where: where}).on('success', function(associationObjects) {
console.log(associationObjects)
self.connectorModel.findAll({where: where}).on('success', function(associatedObjects) {
customEventEmitter.emit('success', associatedObjects)
})
})
return customEventEmitter.run()
} else {
var where = {}
......@@ -71,19 +77,31 @@ HasMany.prototype.injectSetter = function(obj) {
var customEventEmitter = new Utils.CustomEventEmitter(function() {
instance[self.accessors.get]().on('success', function(oldAssociatedObjects) {
if(self.connectorModel) {
var foreignIdentifier = self.target.associations[self.source.tableName].identifier
var destroyChainer = new QueryChainer
// destroy the old association objects
oldAssociatedObjects.forEach(function(associatedObject) {
associatedObject.destroy()
})
oldAssociatedObjects.forEach(function(associatedObject) { destroyChainer.add(associatedObject.destroy()) })
destroyChainer
.run()
.on('failure', function(err) { customEventEmitter.emit('failure', err) })
.on('success', function() {
// create new one
var createChainer = new QueryChainer
newAssociatedObjects.forEach(function(associatedObject) {
var attributes = {}
attributes[self.identifier] = instance.id
attributes[self.foreignIdentifier] = associatedObject.id
self.connectorModel.create(attributes)
attributes[foreignIdentifier] = associatedObject.id
createChainer.add(self.connectorModel.create(attributes))
})
createChainer
.run()
.on('success', function() { customEventEmitter.emit('success', null) })
.on('failure', function(err) { customEventEmitter.emit('failure', err) })
})
customEventEmitter.emit('success', null)
} else {
// clear the old associations
oldAssociatedObjects.forEach(function(associatedObject) {
......@@ -97,13 +115,14 @@ HasMany.prototype.injectSetter = function(obj) {
associatedObject[self.identifier] = instance.id
chainer.add(associatedObject.save())
})
chainer.run()
chainer
.run()
.on('success', function() { customEventEmitter.emit('success', null) })
.on('failure', function() { customEventEmitter.emit('failure', null) })
}
})
})
return customEventEmitter
return customEventEmitter.run()
}
return this
......
......@@ -48,14 +48,12 @@ HasOne.prototype.injectSetter = function(obj) {
}
associatedObject[self.identifier] = obj.id
associatedObject.save().on('success', function() {
customEventEmitter.emit('success', '')
}).on('failure', function(err) {
customEventEmitter.emit('failure', err)
associatedObject.save()
.on('success', function() { customEventEmitter.emit('success', '') })
.on('failure', function(err) { customEventEmitter.emit('failure', err) })
})
})
})
return customEventEmitter
return customEventEmitter.run()
}
return this
......
......@@ -70,7 +70,8 @@ Model.prototype.destroy = function() {
this[this.options.underscored ? 'deleted_at' : 'deletedAt'] = new Date()
return this.save()
} else {
return this.query(QueryGenerator.deleteQuery(this.definition.tableName, this.id))
var identifier = this.options.hasPrimaryKeys ? this.primaryKeyValues : this.id
return this.query(QueryGenerator.deleteQuery(this.definition.tableName, identifier))
}
}
......@@ -96,5 +97,16 @@ Model.prototype.__defineGetter__('values', function() {
return result
})
Model.prototype.__defineGetter__('primaryKeyValues', function() {
var result = {}
, self = this
Utils._.each(this.definition.primaryKeys, function(_, attr) {
result[attr] = self[attr]
})
return result
})
/* Add the instance methods to Model */
Utils._.map(Mixin.instanceMethods, function(fct, name) { Model.prototype[name] = fct})
\ No newline at end of file
......@@ -8,7 +8,7 @@ var QueryChainer = module.exports = function(emitters) {
this.fails = []
this.finished = false
this.runned = false
this.instance = null
this.eventEmitter = null
emitters = emitters || []
emitters.forEach(function(emitter) { self.add(emitter) })
......@@ -28,14 +28,16 @@ QueryChainer.prototype.observeEmitter = function(emitter) {
QueryChainer.prototype.finish = function(result) {
this.finished = (this.finishedEmits == this.emitters.length)
if(this.finished && this.runned) {
this.instance.emit(this.fails.length == 0 ? 'success' : 'failure', result)
var status = this.fails.length == 0 ? 'success' : 'failure'
result = this.fails.length == 0 ? result : this.fails
this.eventEmitter.emit(status, result)
}
}
QueryChainer.prototype.run = function() {
var self = this
this.instance = new Utils.CustomEventEmitter(function() {
this.eventEmitter = new Utils.CustomEventEmitter(function() {
self.runned = true
self.finish()
})
return this.instance
return this.eventEmitter.run()
}
\ No newline at end of file
......@@ -9,8 +9,20 @@ var QueryGenerator = module.exports = {
options = options || {}
var query = "CREATE TABLE IF NOT EXISTS <%= table %> (<%= attributes%>);"
, attrStr = Utils._.map(attributes, function(dataType, attr) { return Utils.addTicks(attr) + " " + dataType}).join(", ")
, primaryKeys = []
, attrStr = Utils._.map(attributes, function(dataType, attr) {
var dt = dataType
if (Utils._.includes(dt, 'PRIMARY KEY')) {
primaryKeys.push(attr)
return Utils.addTicks(attr) + " " + dt.replace(/PRIMARY KEY/, '')
} else {
return Utils.addTicks(attr) + " " + dt
}
}).join(", ")
, values = {table: Utils.addTicks(tableName), attributes: attrStr}
, pkString = primaryKeys.map(function(pk) {return Utils.addTicks(pk)}).join(", ")
if (pkString.length > 0) values.attributes += ", PRIMARY KEY (" + pkString + ")"
return Utils._.template(query)(values)
},
......
......@@ -128,5 +128,13 @@ var Utils = module.exports = {
}
}
Utils.CustomEventEmitter = function(fct) { fct() }
Utils.addEventEmitter(Utils.CustomEventEmitter)
\ No newline at end of file
var CustomEventEmitter = Utils.CustomEventEmitter = function(fct) {
this.fct = fct
}
Utils.addEventEmitter(CustomEventEmitter)
CustomEventEmitter.prototype.run = function() {
var self = this
setTimeout(function(){ self.fct() }, 5) // delay the function call and return the emitter
return this
}
\ No newline at end of file
......@@ -157,5 +157,41 @@ module.exports = {
})
})
})
},
'it should set and get the correct objects - bidirectional': function(exit) {
var User = sequelize.define('User' + parseInt(Math.random() * 99999999), { username: Sequelize.STRING })
var Task = sequelize.define('Task' + parseInt(Math.random() * 99999999), { title: Sequelize.STRING })
User.hasMany(Task, {as: 'Tasks'})
Task.hasMany(User, {as: 'Users'})
User.sync({force: true}).on('success', function() {
Task.sync({force: true}).on('success', function() {
User.create({username: 'name'}).on('success', function(user1) {
User.create({username: 'name2'}).on('success', function(user2) {
Task.create({title: 'task1'}).on('success', function(task1) {
Task.create({title: 'task2'}).on('success', function(task2) {
user1.setTasks([task1, task2]).on('success', function() {
user1.getTasks().on('success', function(tasks) {
assert.eql(tasks.length, 2)
task2.setUsers([user1, user2]).on('success', function() {
task2.getUsers().on('success', function(users) {
assert.eql(users.length, 2)
exit(function(){})
})
})
})
})
})
})
})
})
})
})
}
}
\ 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!