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

Commit feca1473 by Sascha Depold

belongsTo, hasOne and hasMany working for find.

1 parent 830b86b3
...@@ -19,11 +19,11 @@ Mixin.hasOne = function(associatedDAO, options) { ...@@ -19,11 +19,11 @@ Mixin.hasOne = function(associatedDAO, options) {
Mixin.belongsTo = function(associatedDAO, options) { Mixin.belongsTo = function(associatedDAO, options) {
// the id is in this table // the id is in this table
var association = new BelongsTo(this, associatedDAO, Utils._.extend((options||{}), this.options)) var association = new BelongsTo(this, associatedDAO, Utils._.extend((options || {}), this.options))
this.associations[association.associationAccessor] = association.injectAttributes() this.associations[association.associationAccessor] = association.injectAttributes()
association.injectGetter(this.DAO.prototype); association.injectGetter(this.DAO.prototype)
association.injectSetter(this.DAO.prototype); association.injectSetter(this.DAO.prototype)
return this return this
} }
...@@ -33,8 +33,8 @@ Mixin.hasMany = function(associatedDAO, options) { ...@@ -33,8 +33,8 @@ Mixin.hasMany = function(associatedDAO, options) {
var association = new HasMany(this, associatedDAO, Utils._.extend((options||{}), this.options)) var association = new HasMany(this, associatedDAO, Utils._.extend((options||{}), this.options))
this.associations[association.associationAccessor] = association.injectAttributes() this.associations[association.associationAccessor] = association.injectAttributes()
association.injectGetter(this.DAO.prototype); association.injectGetter(this.DAO.prototype)
association.injectSetter(this.DAO.prototype); association.injectSetter(this.DAO.prototype)
return this return this
} }
......
...@@ -149,6 +149,10 @@ module.exports = (function() { ...@@ -149,6 +149,10 @@ module.exports = (function() {
hasJoin = true hasJoin = true
options.include = {} options.include = {}
/*options.include =*/ includes.map(function(include) {
console.log(include instanceof DAOFactory)
})
includes.forEach(function(daoName) { includes.forEach(function(daoName) {
options.include[daoName] = this.daoFactoryManager.getDAO(daoName) options.include[daoName] = this.daoFactoryManager.getDAO(daoName)
...@@ -161,7 +165,10 @@ module.exports = (function() { ...@@ -161,7 +165,10 @@ module.exports = (function() {
this.options.whereCollection = options.where || null this.options.whereCollection = options.where || null
} }
return this.QueryInterface.select(this, this.tableName, options, { type: 'SELECT', hasJoin: hasJoin }) return this.QueryInterface.select(this, this.tableName, options, {
type: 'SELECT',
hasJoin: hasJoin
})
} }
//right now, the caller (has-many-double-linked) is in charge of the where clause //right now, the caller (has-many-double-linked) is in charge of the where clause
...@@ -175,8 +182,16 @@ module.exports = (function() { ...@@ -175,8 +182,16 @@ module.exports = (function() {
return this.QueryInterface.select(this, [this.tableName, joinTableName], optcpy, { type: 'SELECT' }) return this.QueryInterface.select(this, [this.tableName, joinTableName], optcpy, { type: 'SELECT' })
} }
/**
* Search for an instance.
*
* @param {Object} options Options to describe the scope of the search.
* @param {Array} include A list of associations which shall get eagerly loaded. Supported is either { include: [ DaoFactory1, DaoFactory2, ...] } or { include: [ { daoFactory: DaoFactory1, as: 'Alias' } ] }.
* @return {Object} A promise which fires `success`, `error`, `complete` and `sql`.
*/
DAOFactory.prototype.find = function(options) { DAOFactory.prototype.find = function(options) {
var hasJoin = false var hasJoin = false
// no options defined? // no options defined?
// return an emitter which emits null // return an emitter which emits null
if ([null, undefined].indexOf(options) !== -1) { if ([null, undefined].indexOf(options) !== -1) {
...@@ -210,20 +225,13 @@ module.exports = (function() { ...@@ -210,20 +225,13 @@ module.exports = (function() {
options = { where: parsedId } options = { where: parsedId }
} else if (typeof options === 'object') { } else if (typeof options === 'object') {
var options = Utils._.clone(options) options = Utils._.clone(options)
var includes
if (options.hasOwnProperty('include')) { if (options.hasOwnProperty('include')) {
hasJoin = true hasJoin = true
includes = options.include
options.include = {}
includes.forEach(function(daoName) {
options.include[daoName] = this.daoFactoryManager.getDAO(daoName)
if (!options.include[daoName]) { options.include = options.include.map(function(include) {
options.include[daoName] = this.getAssociationByAlias(daoName).target return validateIncludedElement.call(this, include)
}
}.bind(this)) }.bind(this))
} }
...@@ -233,7 +241,11 @@ module.exports = (function() { ...@@ -233,7 +241,11 @@ module.exports = (function() {
options.limit = 1 options.limit = 1
return this.QueryInterface.select(this, this.tableName, options, { plain: true, type: 'SELECT', hasJoin: hasJoin }) return this.QueryInterface.select(this, this.tableName, options, {
plain: true,
type: 'SELECT',
hasJoin: hasJoin
})
} }
DAOFactory.prototype.count = function(options) { DAOFactory.prototype.count = function(options) {
...@@ -260,7 +272,7 @@ module.exports = (function() { ...@@ -260,7 +272,7 @@ module.exports = (function() {
} }
DAOFactory.prototype.build = function(values, options) { DAOFactory.prototype.build = function(values, options) {
options = options || {isNewRecord: true} options = options || { isNewRecord: true }
var self = this var self = this
, instance = new this.DAO(values, this.options, options.isNewRecord) , instance = new this.DAO(values, this.options, options.isNewRecord)
...@@ -283,7 +295,7 @@ module.exports = (function() { ...@@ -283,7 +295,7 @@ module.exports = (function() {
}).success(function (instance) { }).success(function (instance) {
if (instance === null) { if (instance === null) {
for (var attrname in defaults) { for (var attrname in defaults) {
params[attrname] = defaults[attrname]; params[attrname] = defaults[attrname]
} }
self.create(params) self.create(params)
...@@ -292,7 +304,7 @@ module.exports = (function() { ...@@ -292,7 +304,7 @@ module.exports = (function() {
}) })
.error( function (error) { .error( function (error) {
emitter.emit('error', error) emitter.emit('error', error)
}); })
} else { } else {
emitter.emit('success', instance) emitter.emit('success', instance)
} }
...@@ -368,6 +380,40 @@ module.exports = (function() { ...@@ -368,6 +380,40 @@ module.exports = (function() {
}.bind(this)) }.bind(this))
} }
var validateIncludedElement = function(include) {
if (include instanceof DAOFactory) {
include = { daoFactory: include, as: include.tableName }
}
if (typeof include === 'object') {
if (include.hasOwnProperty('daoFactory') && (include.hasOwnProperty('as'))) {
var usesAlias = (include.as !== include.daoFactory.tableName)
, association = (usesAlias ? this.getAssociationByAlias(include.as) : this.getAssociation(include.daoFactory))
// check if the current daoFactory is actually associated with the passed daoFactory
if (!!association) {
include.association = association
return include
} else {
var msg = include.daoFactory.name
if (usesAlias) {
msg += " (" + include.as + ")"
}
msg += " is not associated to " + this.name + "!"
throw new Error(msg)
}
} else {
throw new Error('Include malformed. Expected attributes: daoFactory, as')
}
} else {
throw new Error('Include unexpected. Element has to be either an instance of DAOFactory or an object.')
}
}
Utils._.extend(DAOFactory.prototype, require("./associations/mixin")) Utils._.extend(DAOFactory.prototype, require("./associations/mixin"))
return DAOFactory return DAOFactory
......
...@@ -131,49 +131,73 @@ module.exports = (function() { ...@@ -131,49 +131,73 @@ module.exports = (function() {
if (options.include) { if (options.include) {
var optAttributes = [options.table + '.*'] var optAttributes = [options.table + '.*']
for (var daoName in options.include) { options.include.forEach(function(include) {
if (options.include.hasOwnProperty(daoName)) { //SELECT `UserWithNames`.*, `Tasks`.`title` AS `Tasks.title`, `Tasks`.`id` AS `Tasks.id`, `Tasks`.`createdAt` AS `Tasks.createdAt`, `Tasks`.`updatedAt` AS `Tasks.updatedAt`, `TaskFROM `UserWithNames` LEFT OUTER JOIN `Tasks` ON `Tasks`.`UserWithNameId`=`UserWithNames`.`id` WHERE `UserWithNames`.`id`=1;
var dao = options.include[daoName] //SELECT `Tasks`.*, `Workers`.`name` AS `Workers.name`, `Workers`.`id` AS `Workers.id`, `Workers`.`createdAt` AS `Workers.createdAt`, `Workers`.`updatedAt` AS `Workers.updatedAt` FROM `Tasks` LEFT OUTER JOIN `Workers` ON `Workers`.`WorkerId` = `Tasks`.`id` WHERE `Tasks`.`id`=1;
, daoFactory = dao.daoFactoryManager.getDAO(tableName, { var attributes = Object.keys(include.daoFactory.attributes).map(function(attr) {
attribute: 'tableName' var template = Utils._.template("`<%= table %>`.`<%= attr %>` AS `<%= as %>.<%= attr %>`")
return template({
table: include.daoFactory.tableName,
as: include.as,
attr: attr
})
}) })
, _tableName = Utils.addTicks(dao.tableName)
, association = dao.getAssociation(daoFactory)
if (association.connectorDAO) {
var foreignIdentifier = Object.keys(association.connectorDAO.rawAttributes).filter(function(attrName) {
return (!!attrName.match(/.+Id$/) || !!attrName.match(/.+_id$/)) && (attrName !== association.identifier)
})[0]
query += ' LEFT OUTER JOIN ' + Utils.addTicks(association.connectorDAO.tableName) + ' ON '
query += Utils.addTicks(association.connectorDAO.tableName) + '.'
query += Utils.addTicks(foreignIdentifier) + '='
query += Utils.addTicks(table) + '.' + Utils.addTicks('id')
query += ' LEFT OUTER JOIN ' + Utils.addTicks(dao.tableName) + ' ON '
query += Utils.addTicks(dao.tableName) + '.'
query += Utils.addTicks('id') + '='
query += Utils.addTicks(association.connectorDAO.tableName) + '.' + Utils.addTicks(association.identifier)
} else {
query += ' LEFT OUTER JOIN ' + Utils.addTicks(dao.tableName) + ' ON '
query += Utils.addTicks(association.associationType === 'BelongsTo' ? dao.tableName : tableName) + '.'
query += Utils.addTicks(association.identifier) + '='
query += Utils.addTicks(association.associationType === 'BelongsTo' ? tableName : dao.tableName) + '.' + Utils.addTicks('id')
}
var aliasAssoc = daoFactory.getAssociationByAlias(daoName) optAttributes = optAttributes.concat(attributes)
, aliasName = !!aliasAssoc ? Utils.addTicks(daoName) : _tableName
optAttributes = optAttributes.concat( var joinQuery = " LEFT OUTER JOIN `<%= table %>` ON `<%= tableLeft %>`.`<%= attrLeft %>` = `<%= tableRight %>`.`<%= attrRight %>`"
Object.keys(dao.attributes).map(function(attr) { query += Utils._.template(joinQuery)({
return '' + table: include.daoFactory.tableName,
[_tableName, Utils.addTicks(attr)].join('.') + tableLeft: ((include.association.associationType === 'BelongsTo') ? include.daoFactory.tableName : tableName),
' AS ' + attrLeft: 'id',
Utils.addTicks([aliasName, attr].join('.')) tableRight: ((include.association.associationType === 'BelongsTo') ? tableName : include.daoFactory.tableName),
attrRight: include.association.identifier
}) })
) })
}
} // for (var daoFactory in options.include) {
// if (options.include.hasOwnProperty(daoFactory)) {
// var dao = options.include[daoName]
// , daoFactory = dao.daoFactoryManager.getDAO(tableName, {
// attribute: 'tableName'
// })
// , _tableName = Utils.addTicks(dao.tableName)
// , association = dao.getAssociation(daoFactory)
// if (association.connectorDAO) {
// var foreignIdentifier = Object.keys(association.connectorDAO.rawAttributes).filter(function(attrName) {
// return (!!attrName.match(/.+Id$/) || !!attrName.match(/.+_id$/)) && (attrName !== association.identifier)
// })[0]
// query += ' LEFT OUTER JOIN ' + Utils.addTicks(association.connectorDAO.tableName) + ' ON '
// query += Utils.addTicks(association.connectorDAO.tableName) + '.'
// query += Utils.addTicks(foreignIdentifier) + '='
// query += Utils.addTicks(table) + '.' + Utils.addTicks('id')
// query += ' LEFT OUTER JOIN ' + Utils.addTicks(dao.tableName) + ' ON '
// query += Utils.addTicks(dao.tableName) + '.'
// query += Utils.addTicks('id') + '='
// query += Utils.addTicks(association.connectorDAO.tableName) + '.' + Utils.addTicks(association.identifier)
// } else {
// query += ' LEFT OUTER JOIN ' + Utils.addTicks(dao.tableName) + ' ON '
// query += Utils.addTicks(association.associationType === 'BelongsTo' ? dao.tableName : tableName) + '.'
// query += Utils.addTicks(association.identifier) + '='
// query += Utils.addTicks(association.associationType === 'BelongsTo' ? tableName : dao.tableName) + '.' + Utils.addTicks('id')
// }
// var aliasAssoc = daoFactory.getAssociationByAlias(daoName)
// , aliasName = !!aliasAssoc ? Utils.addTicks(daoName) : _tableName
// optAttributes = optAttributes.concat(
// Object.keys(dao.attributes).map(function(attr) {
// return '' +
// [_tableName, Utils.addTicks(attr)].join('.') +
// ' AS ' +
// Utils.addTicks([aliasName, attr].join('.'))
// })
// )
// }
// }
options.attributes = optAttributes.join(', ') options.attributes = optAttributes.join(', ')
} }
......
...@@ -199,13 +199,14 @@ module.exports = (function() { ...@@ -199,13 +199,14 @@ module.exports = (function() {
QueryInterface.prototype.select = function(factory, tableName, options, queryOptions) { QueryInterface.prototype.select = function(factory, tableName, options, queryOptions) {
var sql = this.QueryGenerator.selectQuery(tableName, options) var sql = this.QueryGenerator.selectQuery(tableName, options)
queryOptions = Utils._.extend({}, queryOptions, { include: options.include })
return queryAndEmit.call(this, [sql, factory, queryOptions], 'select') return queryAndEmit.call(this, [sql, factory, queryOptions], 'select')
} }
QueryInterface.prototype.rawSelect = function(tableName, options, attributeSelector) { QueryInterface.prototype.rawSelect = function(tableName, options, attributeSelector) {
var self = this var self = this
if (attributeSelector == undefined) { if (attributeSelector === undefined) {
throw new Error('Please pass an attribute selector!') throw new Error('Please pass an attribute selector!')
} }
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!