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

Commit 4dbbb89b by Sascha Depold

private method scoping for associations

1 parent 3e57b469
var Utils = require("./../utils")
, DataTypes = require('./../data-types')
var BelongsTo = module.exports = function(srcModel, targetModel, options) {
this.source = srcModel
this.target = targetModel
this.options = options
this.isSelfAssociation = (this.source.tableName == this.target.tableName)
if(this.isSelfAssociation && !this.options.foreignKey && !!this.options.as)
this.options.foreignKey = Utils._.underscoredIf(Utils.singularize(this.options.as) + "Id", this.source.options.underscored)
this.associationAccessor = this.isSelfAssociation
? Utils.combineTableNames(this.target.tableName, this.options.as || this.target.tableName)
: this.target.tableName
}
// the id is in the source table
BelongsTo.prototype.injectAttributes = function() {
var newAttributes = {}
this.identifier = this.options.foreignKey || Utils._.underscoredIf(Utils.singularize(this.target.tableName) + "Id", this.source.options.underscored)
newAttributes[this.identifier] = { type: DataTypes.INTEGER }
Utils._.extend(this.source.attributes, Utils.simplifyAttributes(newAttributes))
return this
}
BelongsTo.prototype.injectGetter = function(obj) {
var self = this
, accessor = Utils._.camelize('get_' + (this.options.as || Utils.singularize(this.target.tableName)))
obj[accessor] = function() {
var id = obj[self.identifier]
return self.target.find(id)
module.exports = (function() {
var BelongsTo = function(srcModel, targetModel, options) {
this.source = srcModel
this.target = targetModel
this.options = options
this.isSelfAssociation = (this.source.tableName == this.target.tableName)
if(this.isSelfAssociation && !this.options.foreignKey && !!this.options.as)
this.options.foreignKey = Utils._.underscoredIf(Utils.singularize(this.options.as) + "Id", this.source.options.underscored)
this.associationAccessor = this.isSelfAssociation
? Utils.combineTableNames(this.target.tableName, this.options.as || this.target.tableName)
: this.target.tableName
}
// the id is in the source table
BelongsTo.prototype.injectAttributes = function() {
var newAttributes = {}
this.identifier = this.options.foreignKey || Utils._.underscoredIf(Utils.singularize(this.target.tableName) + "Id", this.source.options.underscored)
newAttributes[this.identifier] = { type: DataTypes.INTEGER }
Utils._.extend(this.source.attributes, Utils.simplifyAttributes(newAttributes))
return this
}
BelongsTo.prototype.injectGetter = function(obj) {
var self = this
, accessor = Utils._.camelize('get_' + (this.options.as || Utils.singularize(this.target.tableName)))
obj[accessor] = function() {
var id = obj[self.identifier]
return self.target.find(id)
}
return this
}
return this
}
BelongsTo.prototype.injectSetter = function(obj) {
var self = this
, accessor = Utils._.camelize('set_' + (this.options.as || Utils.singularize(this.target.tableName)))
obj[accessor] = function(associatedObject) {
obj[self.identifier] = associatedObject ? associatedObject.id : null
return obj.save()
BelongsTo.prototype.injectSetter = function(obj) {
var self = this
, accessor = Utils._.camelize('set_' + (this.options.as || Utils.singularize(this.target.tableName)))
obj[accessor] = function(associatedObject) {
obj[self.identifier] = associatedObject ? associatedObject.id : null
return obj.save()
}
return this
}
return this
}
\ No newline at end of file
return BelongsTo
})()
var Utils = require('./../utils')
var HasManyDoubleLinked = module.exports = function(definition, instance) {
this.__definition = definition
this.instance = instance
}
HasManyDoubleLinked.prototype.injectGetter = function() {
var self = this
var customEventEmitter = new Utils.CustomEventEmitter(function() {
var where = {}
where[self.__definition.identifier] = self.instance.id
var primaryKeys = Utils._.keys(self.__definition.connectorModel.rawAttributes)
, foreignKey = primaryKeys.filter(function(pk) { return pk != self.__definition.identifier })[0]
self.__definition.connectorModel.findAll({where: where}).on('success', function(associatedObjects) {
var ids = associatedObjects.map(function(obj) { return obj[foreignKey] })
if (ids.length == 0) {
customEventEmitter.emit('success', [])
} else {
self.__definition.target.findAll({where: 'id in (' + ids.join(", ") + ')'})
.on('success', function(objects) { customEventEmitter.emit('success', objects) })
.on('failure', function(err){ customEventEmitter.emit('failure', err) })
}
})
})
return customEventEmitter.run()
}
HasManyDoubleLinked.prototype.destroyObsoleteAssociations = function(oldAssociations, newAssociations) {
var self = this
module.exports = (function() {
var HasManyDoubleLinked = function(definition, instance) {
this.__definition = definition
this.instance = instance
}
var emitter = new Utils.CustomEventEmitter(function() {
var chainer = new Utils.QueryChainer
var foreignIdentifier = self.__definition.target.associations[self.__definition.associationAccessor].identifier
var obsoleteAssociations = oldAssociations.filter(function(obj) { return !obj.equalsOneOf(newAssociations) })
HasManyDoubleLinked.prototype.injectGetter = function() {
var self = this
if(obsoleteAssociations.length == 0)
return emitter.emit('success', null)
var customEventEmitter = new Utils.CustomEventEmitter(function() {
var where = {}
where[self.__definition.identifier] = self.instance.id
obsoleteAssociations.forEach(function(associatedObject) {
var where = {}
, primaryKeys = Utils._.keys(self.__definition.connectorModel.rawAttributes)
var primaryKeys = Utils._.keys(self.__definition.connectorModel.rawAttributes)
, foreignKey = primaryKeys.filter(function(pk) { return pk != self.__definition.identifier })[0]
where[self.__definition.identifier] = self.instance.id
where[foreignKey] = associatedObject.id
self.__definition.connectorModel.find({where: where}).on('success', function(connector) {
chainer.add(connector.destroy())
self.__definition.connectorModel.findAll({where: where}).on('success', function(associatedObjects) {
var ids = associatedObjects.map(function(obj) { return obj[foreignKey] })
if(chainer.emitters.length == obsoleteAssociations.length) {
// found all obsolete connectors and will delete them now
chainer
.run()
.on('success', function() { emitter.emit('success', null) })
.on('failure', function(err) { emitter.emit('failure', err) })
if (ids.length == 0) {
customEventEmitter.emit('success', [])
} else {
self.__definition.target.findAll({where: 'id in (' + ids.join(", ") + ')'})
.on('success', function(objects) { customEventEmitter.emit('success', objects) })
.on('failure', function(err){ customEventEmitter.emit('failure', err) })
}
})
})
})
return emitter.run()
}
HasManyDoubleLinked.prototype.injectSetter = function(emitter, oldAssociations, newAssociations) {
var self = this
this.destroyObsoleteAssociations(oldAssociations, newAssociations)
.on('failure', function(err) { emitter.emit('failure', err) })
.on('success', function() {
var chainer = new Utils.QueryChainer
, association = self.__definition.target.associations[self.__definition.associationAccessor]
, foreignIdentifier = association.isSelfAssociation ? association.foreignIdentifier : association.identifier
, unassociatedObjects = newAssociations.filter(function(obj) { return !obj.equalsOneOf(oldAssociations) })
unassociatedObjects.forEach(function(unassociatedObject) {
var attributes = {}
attributes[self.__definition.identifier] = self.instance.id
attributes[foreignIdentifier] = unassociatedObject.id
chainer.add(self.__definition.connectorModel.create(attributes))
return customEventEmitter.run()
}
HasManyDoubleLinked.prototype.injectSetter = function(emitter, oldAssociations, newAssociations) {
var self = this
destroyObsoleteAssociations.call(this, oldAssociations, newAssociations)
.on('failure', function(err) { emitter.emit('failure', err) })
.on('success', function() {
var chainer = new Utils.QueryChainer
, association = self.__definition.target.associations[self.__definition.associationAccessor]
, foreignIdentifier = association.isSelfAssociation ? association.foreignIdentifier : association.identifier
, unassociatedObjects = newAssociations.filter(function(obj) { return !obj.equalsOneOf(oldAssociations) })
unassociatedObjects.forEach(function(unassociatedObject) {
var attributes = {}
attributes[self.__definition.identifier] = self.instance.id
attributes[foreignIdentifier] = unassociatedObject.id
chainer.add(self.__definition.connectorModel.create(attributes))
})
chainer
.run()
.on('success', function() { emitter.emit('success', newAssociations) })
.on('failure', function(err) { emitter.emit('failure', err) })
})
}
// private
var destroyObsoleteAssociations = function(oldAssociations, newAssociations) {
var self = this
var emitter = new Utils.CustomEventEmitter(function() {
var chainer = new Utils.QueryChainer
var foreignIdentifier = self.__definition.target.associations[self.__definition.associationAccessor].identifier
var obsoleteAssociations = oldAssociations.filter(function(obj) { return !obj.equalsOneOf(newAssociations) })
if(obsoleteAssociations.length == 0)
return emitter.emit('success', null)
chainer
.run()
.on('success', function() { emitter.emit('success', newAssociations) })
.on('failure', function(err) { emitter.emit('failure', err) })
obsoleteAssociations.forEach(function(associatedObject) {
var where = {}
, primaryKeys = Utils._.keys(self.__definition.connectorModel.rawAttributes)
, foreignKey = primaryKeys.filter(function(pk) { return pk != self.__definition.identifier })[0]
where[self.__definition.identifier] = self.instance.id
where[foreignKey] = associatedObject.id
self.__definition.connectorModel.find({where: where}).on('success', function(connector) {
chainer.add(connector.destroy())
if(chainer.emitters.length == obsoleteAssociations.length) {
// found all obsolete connectors and will delete them now
chainer
.run()
.on('success', function() { emitter.emit('success', null) })
.on('failure', function(err) { emitter.emit('failure', err) })
}
})
})
})
}
return emitter.run()
}
return HasManyDoubleLinked
})()
var Utils = require('./../utils')
var HasManySingleLinked = module.exports = function(definition, instance) {
this.__definition = definition
this.instance = instance
}
module.exports = (function() {
var HasManySingleLinked = function(definition, instance) {
this.__definition = definition
this.instance = instance
}
HasManySingleLinked.prototype.injectGetter = function() {
var where = {}
HasManySingleLinked.prototype.injectGetter = function() {
var where = {}
where[this.__definition.identifier] = this.instance.id
return this.__definition.target.findAll({where: where})
}
where[this.__definition.identifier] = this.instance.id
return this.__definition.target.findAll({where: where})
}
HasManySingleLinked.prototype.injectSetter = function(emitter, oldAssociations, newAssociations) {
var self = this
HasManySingleLinked.prototype.injectSetter = function(emitter, oldAssociations, newAssociations) {
var self = this
// clear the old associations
oldAssociations.forEach(function(associatedObject) {
associatedObject[self.__definition.identifier] = null
associatedObject.save()
})
// clear the old associations
oldAssociations.forEach(function(associatedObject) {
associatedObject[self.__definition.identifier] = null
associatedObject.save()
})
// set the new one
var chainer = new Utils.QueryChainer
newAssociations.forEach(function(associatedObject) {
associatedObject[self.__definition.identifier] = self.instance.id
chainer.add(associatedObject.save())
})
chainer
.run()
.on('success', function() { emitter.emit('success', newAssociations) })
.on('failure', function(err) { emitter.emit('failure', err) })
}
// set the new one
var chainer = new Utils.QueryChainer
newAssociations.forEach(function(associatedObject) {
associatedObject[self.__definition.identifier] = self.instance.id
chainer.add(associatedObject.save())
})
chainer
.run()
.on('success', function() { emitter.emit('success', newAssociations) })
.on('failure', function(err) { emitter.emit('failure', err) })
}
return HasManySingleLinked
})()
......@@ -4,124 +4,128 @@ var Utils = require("./../utils")
var HasManySingleLinked = require("./has-many-single-linked")
, HasManyMultiLinked = require("./has-many-double-linked")
var HasMany = module.exports = function(srcModel, targetModel, options) {
this.source = srcModel
this.target = targetModel
this.options = options
this.isSelfAssociation = (this.source.tableName == this.target.tableName)
this.associationAccessor = this.combinedName = Utils.combineTableNames(
this.source.tableName,
this.isSelfAssociation ? (this.options.as || this.target.tableName) : this.target.tableName
)
var as = (this.options.as || Utils.pluralize(this.target.tableName))
this.accessors = {
get: Utils._.camelize('get_' + as),
set: Utils._.camelize('set_' + as),
add: Utils._.camelize(Utils.singularize('add_' + as)),
remove: Utils._.camelize(Utils.singularize('remove_' + as))
module.exports = (function() {
var HasMany = function(srcModel, targetModel, options) {
this.source = srcModel
this.target = targetModel
this.options = options
this.isSelfAssociation = (this.source.tableName == this.target.tableName)
this.associationAccessor = this.combinedName = Utils.combineTableNames(
this.source.tableName,
this.isSelfAssociation ? (this.options.as || this.target.tableName) : this.target.tableName
)
var as = (this.options.as || Utils.pluralize(this.target.tableName))
this.accessors = {
get: Utils._.camelize('get_' + as),
set: Utils._.camelize('set_' + as),
add: Utils._.camelize(Utils.singularize('add_' + as)),
remove: Utils._.camelize(Utils.singularize('remove_' + as))
}
}
}
// the id is in the target table
// or in an extra table which connects two tables
HasMany.prototype.injectAttributes = function() {
var multiAssociation = this.target.associations.hasOwnProperty(this.associationAccessor)
this.identifier = this.options.foreignKey || Utils._.underscoredIf(Utils.singularize(this.source.tableName) + "Id", this.options.underscored)
// is there already a single sided association between the source and the target?
// or is the association on the model itself?
if (this.isSelfAssociation || multiAssociation) {
// remove the obsolete association identifier from the source
if(this.isSelfAssociation) {
this.foreignIdentifier = (this.options.as || this.target.tableName) + 'Id'
// the id is in the target table
// or in an extra table which connects two tables
HasMany.prototype.injectAttributes = function() {
var multiAssociation = this.target.associations.hasOwnProperty(this.associationAccessor)
this.identifier = this.options.foreignKey || Utils._.underscoredIf(Utils.singularize(this.source.tableName) + "Id", this.options.underscored)
// is there already a single sided association between the source and the target?
// or is the association on the model itself?
if (this.isSelfAssociation || multiAssociation) {
// remove the obsolete association identifier from the source
if(this.isSelfAssociation) {
this.foreignIdentifier = (this.options.as || this.target.tableName) + 'Id'
} else {
this.foreignIdentifier = this.target.associations[this.associationAccessor].identifier
delete this.source.attributes[this.foreignIdentifier]
}
// define a new model, which connects the models
var combinedTableAttributes = {}
combinedTableAttributes[this.identifier] = {type:DataTypes.INTEGER, primaryKey: true}
combinedTableAttributes[this.foreignIdentifier] = {type:DataTypes.INTEGER, primaryKey: true}
this.connectorModel = this.source.modelManager.sequelize.define(this.combinedName, combinedTableAttributes)
if(!this.isSelfAssociation) this.target.associations[this.associationAccessor].connectorModel = this.connectorModel
this.connectorModel.sync()
} else {
this.foreignIdentifier = this.target.associations[this.associationAccessor].identifier
delete this.source.attributes[this.foreignIdentifier]
var newAttributes = {}
newAttributes[this.identifier] = { type: DataTypes.INTEGER }
Utils._.extend(this.target.attributes, Utils.simplifyAttributes(newAttributes))
}
// define a new model, which connects the models
var combinedTableAttributes = {}
combinedTableAttributes[this.identifier] = {type:DataTypes.INTEGER, primaryKey: true}
combinedTableAttributes[this.foreignIdentifier] = {type:DataTypes.INTEGER, primaryKey: true}
this.connectorModel = this.source.modelManager.sequelize.define(this.combinedName, combinedTableAttributes)
if(!this.isSelfAssociation) this.target.associations[this.associationAccessor].connectorModel = this.connectorModel
this.connectorModel.sync()
} else {
var newAttributes = {}
newAttributes[this.identifier] = { type: DataTypes.INTEGER }
Utils._.extend(this.target.attributes, Utils.simplifyAttributes(newAttributes))
return this
}
return this
}
HasMany.prototype.injectGetter = function(obj) {
var self = this
HasMany.prototype.injectGetter = function(obj) {
var self = this
obj[this.accessors.get] = function() {
var Class = self.connectorModel ? HasManyMultiLinked : HasManySingleLinked
return new Class(self, this).injectGetter()
obj[this.accessors.get] = function() {
var Class = self.connectorModel ? HasManyMultiLinked : HasManySingleLinked
return new Class(self, this).injectGetter()
}
return this
}
return this
}
HasMany.prototype.injectSetter = function(obj) {
var self = this
HasMany.prototype.injectSetter = function(obj) {
var self = this
obj[this.accessors.set] = function(newAssociatedObjects) {
var instance = this
obj[this.accessors.set] = function(newAssociatedObjects) {
var instance = this
// define the returned customEventEmitter, which will emit the success event once everything is done
var customEventEmitter = new Utils.CustomEventEmitter(function() {
instance[self.accessors.get]().on('success', function(oldAssociatedObjects) {
var Class = self.connectorModel ? HasManyMultiLinked : HasManySingleLinked
new Class(self, instance).injectSetter(customEventEmitter, oldAssociatedObjects, newAssociatedObjects)
// define the returned customEventEmitter, which will emit the success event once everything is done
var customEventEmitter = new Utils.CustomEventEmitter(function() {
instance[self.accessors.get]().on('success', function(oldAssociatedObjects) {
var Class = self.connectorModel ? HasManyMultiLinked : HasManySingleLinked
new Class(self, instance).injectSetter(customEventEmitter, oldAssociatedObjects, newAssociatedObjects)
})
})
})
return customEventEmitter.run()
}
obj[this.accessors.add] = function(newAssociatedObject) {
var instance = this
var customEventEmitter = new Utils.CustomEventEmitter(function() {
instance[self.accessors.get]()
.on('failure', function(err){ customEventEmitter.emit('failure', err)})
.on('success', function(currentAssociatedObjects) {
if(!newAssociatedObject.equalsOneOf(currentAssociatedObjects))
currentAssociatedObjects.push(newAssociatedObject)
instance[self.accessors.set](currentAssociatedObjects)
.on('success', function(instances) { customEventEmitter.emit('success', instances) })
return customEventEmitter.run()
}
obj[this.accessors.add] = function(newAssociatedObject) {
var instance = this
var customEventEmitter = new Utils.CustomEventEmitter(function() {
instance[self.accessors.get]()
.on('failure', function(err){ customEventEmitter.emit('failure', err)})
.on('success', function(currentAssociatedObjects) {
if(!newAssociatedObject.equalsOneOf(currentAssociatedObjects))
currentAssociatedObjects.push(newAssociatedObject)
instance[self.accessors.set](currentAssociatedObjects)
.on('success', function(instances) { customEventEmitter.emit('success', instances) })
.on('failure', function(err) { customEventEmitter.emit('failure', err) })
})
})
return customEventEmitter.run()
}
obj[this.accessors.remove] = function(oldAssociatedObject) {
var instance = this
var customEventEmitter = new Utils.CustomEventEmitter(function() {
instance[self.accessors.get]().on('success', function(currentAssociatedObjects) {
var newAssociations = []
currentAssociatedObjects.forEach(function(association) {
if(!Utils._.isEqual(oldAssociatedObject.identifiers, association.identifiers))
newAssociations.push(association)
})
instance[self.accessors.set](newAssociations)
.on('success', function() { customEventEmitter.emit('success', null) })
.on('failure', function(err) { customEventEmitter.emit('failure', err) })
})
})
return customEventEmitter.run()
}
obj[this.accessors.remove] = function(oldAssociatedObject) {
var instance = this
var customEventEmitter = new Utils.CustomEventEmitter(function() {
instance[self.accessors.get]().on('success', function(currentAssociatedObjects) {
var newAssociations = []
currentAssociatedObjects.forEach(function(association) {
if(!Utils._.isEqual(oldAssociatedObject.identifiers, association.identifiers))
newAssociations.push(association)
})
instance[self.accessors.set](newAssociations)
.on('success', function() { customEventEmitter.emit('success', null) })
.on('failure', function(err) { customEventEmitter.emit('failure', err) })
})
})
return customEventEmitter.run()
return customEventEmitter.run()
}
return this
}
return this
}
\ No newline at end of file
return HasMany
})()
var Utils = require("./../utils")
, DataTypes = require('./../data-types')
var HasOne = module.exports = function(srcModel, targetModel, options) {
this.source = srcModel
this.target = targetModel
this.options = options
this.isSelfAssociation = (this.source.tableName == this.target.tableName)
if(this.isSelfAssociation && !this.options.foreignKey && !!this.options.as)
this.options.foreignKey = Utils._.underscoredIf(Utils.singularize(this.options.as) + "Id", this.options.underscored)
this.associationAccessor = this.isSelfAssociation
? Utils.combineTableNames(this.target.tableName, this.options.as || this.target.tableName)
: this.target.tableName
this.accessors = {
get: Utils._.camelize('get_' + (this.options.as || Utils.singularize(this.target.tableName))),
set: Utils._.camelize('set_' + (this.options.as || Utils.singularize(this.target.tableName)))
module.exports = (function() {
var HasOne = function(srcModel, targetModel, options) {
this.source = srcModel
this.target = targetModel
this.options = options
this.isSelfAssociation = (this.source.tableName == this.target.tableName)
if(this.isSelfAssociation && !this.options.foreignKey && !!this.options.as)
this.options.foreignKey = Utils._.underscoredIf(Utils.singularize(this.options.as) + "Id", this.options.underscored)
this.associationAccessor = this.isSelfAssociation
? Utils.combineTableNames(this.target.tableName, this.options.as || this.target.tableName)
: this.target.tableName
this.accessors = {
get: Utils._.camelize('get_' + (this.options.as || Utils.singularize(this.target.tableName))),
set: Utils._.camelize('set_' + (this.options.as || Utils.singularize(this.target.tableName)))
}
}
// the id is in the target table
HasOne.prototype.injectAttributes = function() {
var newAttributes = {}
this.identifier = this.options.foreignKey || Utils._.underscoredIf(Utils.singularize(this.source.tableName) + "Id", this.options.underscored)
newAttributes[this.identifier] = { type: DataTypes.INTEGER }
Utils._.extend(this.target.attributes, Utils.simplifyAttributes(newAttributes))
return this
}
}
// the id is in the target table
HasOne.prototype.injectAttributes = function() {
var newAttributes = {}
this.identifier = this.options.foreignKey || Utils._.underscoredIf(Utils.singularize(this.source.tableName) + "Id", this.options.underscored)
newAttributes[this.identifier] = { type: DataTypes.INTEGER }
Utils._.extend(this.target.attributes, Utils.simplifyAttributes(newAttributes))
return this
}
HasOne.prototype.injectGetter = function(obj) {
var self = this
obj[this.accessors.get] = function() {
var id = obj.id
, where = {}
where[self.identifier] = id
return self.target.find({where: where})
HasOne.prototype.injectGetter = function(obj) {
var self = this
obj[this.accessors.get] = function() {
var id = obj.id
, where = {}
where[self.identifier] = id
return self.target.find({where: where})
}
return this
}
return this
}
HasOne.prototype.injectSetter = function(obj) {
var self = this
obj[this.accessors.set] = function(associatedObject) {
var customEventEmitter = new Utils.CustomEventEmitter(function() {
obj[self.accessors.get]().on('success', function(oldObj) {
if(oldObj) {
oldObj[self.identifier] = null
oldObj.save()
}
associatedObject[self.identifier] = obj.id
associatedObject.save()
.on('success', function() { customEventEmitter.emit('success', associatedObject) })
.on('failure', function(err) { customEventEmitter.emit('failure', err) })
HasOne.prototype.injectSetter = function(obj) {
var self = this
obj[this.accessors.set] = function(associatedObject) {
var customEventEmitter = new Utils.CustomEventEmitter(function() {
obj[self.accessors.get]().on('success', function(oldObj) {
if(oldObj) {
oldObj[self.identifier] = null
oldObj.save()
}
associatedObject[self.identifier] = obj.id
associatedObject.save()
.on('success', function() { customEventEmitter.emit('success', associatedObject) })
.on('failure', function(err) { customEventEmitter.emit('failure', err) })
})
})
})
return customEventEmitter.run()
return customEventEmitter.run()
}
return this
}
return this
}
\ No newline at end of file
return HasOne
})()
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!