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

Commit df76b18a by Mick Hansen

Merge branch 'master' into milestones/2.0.0

2 parents 34ef9fbc 09ac0969
...@@ -10,24 +10,25 @@ module.exports = (function() { ...@@ -10,24 +10,25 @@ module.exports = (function() {
this.options = options this.options = options
this.isSingleAssociation = true this.isSingleAssociation = true
this.isSelfAssociation = (this.source.tableName == this.target.tableName) this.isSelfAssociation = (this.source.tableName == this.target.tableName)
this.as = this.options.as
if (this.isSelfAssociation && !this.options.foreignKey && !!this.options.as) { if (this.isSelfAssociation && !this.options.foreignKey && !!this.as) {
this.options.foreignKey = Utils._.underscoredIf(Utils.singularize(this.options.as, this.source.options.language) + "Id", this.source.options.underscored) this.options.foreignKey = Utils._.underscoredIf(Utils.singularize(this.source.tableName, this.source.options.language) + "Id", this.source.options.underscored)
} }
if (!this.options.as) { if (!this.as) {
this.options.as = Utils.singularize(this.target.tableName, this.target.options.language) this.as = this.options.as = Utils.singularize(this.target.tableName, this.target.options.language)
} }
this.associationAccessor = this.isSelfAssociation this.associationAccessor = this.isSelfAssociation
? Utils.combineTableNames(this.target.tableName, this.options.as) ? Utils.combineTableNames(this.target.tableName, this.as)
: this.options.as : this.as
this.options.useHooks = options.useHooks this.options.useHooks = options.useHooks
this.accessors = { this.accessors = {
get: Utils._.camelize('get_' + this.options.as), get: Utils._.camelize('get_' + this.as),
set: Utils._.camelize('set_' + this.options.as) set: Utils._.camelize('set_' + this.as)
} }
} }
...@@ -38,6 +39,7 @@ module.exports = (function() { ...@@ -38,6 +39,7 @@ module.exports = (function() {
, keyType = ((this.target.hasPrimaryKeys && targetKeys.length === 1) ? this.target.rawAttributes[targetKeys[0]].type : DataTypes.INTEGER) , keyType = ((this.target.hasPrimaryKeys && targetKeys.length === 1) ? this.target.rawAttributes[targetKeys[0]].type : DataTypes.INTEGER)
this.identifier = this.options.foreignKey || Utils._.underscoredIf(Utils.singularize(this.target.tableName, this.target.options.language) + "Id", this.source.options.underscored) this.identifier = this.options.foreignKey || Utils._.underscoredIf(Utils.singularize(this.target.tableName, this.target.options.language) + "Id", this.source.options.underscored)
newAttributes[this.identifier] = { type: this.options.keyType || keyType } newAttributes[this.identifier] = { type: this.options.keyType || keyType }
Helpers.addForeignKeyConstraints(newAttributes[this.identifier], this.target, this.source, this.options) Helpers.addForeignKeyConstraints(newAttributes[this.identifier], this.target, this.source, this.options)
Utils._.defaults(this.source.rawAttributes, newAttributes) Utils._.defaults(this.source.rawAttributes, newAttributes)
......
...@@ -21,7 +21,7 @@ module.exports = (function() { ...@@ -21,7 +21,7 @@ module.exports = (function() {
, options = _options || {} , options = _options || {}
, queryOptions = {} , queryOptions = {}
, targetAssociation = self.association.targetAssociation , targetAssociation = self.association.targetAssociation
//fully qualify //fully qualify
var instancePrimaryKeys = Object.keys(self.instance.daoFactory.primaryKeys) var instancePrimaryKeys = Object.keys(self.instance.daoFactory.primaryKeys)
, instancePrimaryKey = instancePrimaryKeys.length > 0 ? instancePrimaryKeys[0] : 'id' , instancePrimaryKey = instancePrimaryKeys.length > 0 ? instancePrimaryKeys[0] : 'id'
......
...@@ -56,31 +56,38 @@ module.exports = (function() { ...@@ -56,31 +56,38 @@ module.exports = (function() {
} }
/* /*
* Find partner DAOFactory if present, to identify double linked association * If self association, this association is target association
*/ */
if (this.through) { if (this.isSelfAssociation) {
_.each(this.target.associations, function (association, accessor) { this.targetAssociation = this
if (self.source === association.target) { }
var paired = false
/*
// If through is default, we determine pairing by the accesor value (i.e. DAOFactory's using as won't pair, but regular ones will) * Else find partner DAOFactory if present, to identify double linked association
if (self.through === true && accessor === self.associationAccessor) { */
paired = true else if (this.through) {
} _.each(this.target.associations, function (association, accessor) {
// If through is not default, determine pairing by through value (model/string) if (self.source === association.target) {
if (self.through !== true && self.options.through === association.options.through) { var paired = false
paired = true
} // If through is default, we determine pairing by the accesor value (i.e. DAOFactory's using as won't pair, but regular ones will)
// If paired, set properties identifying both associations as double linked, and allow them to each eachtoerh if (self.through === true && accessor === self.associationAccessor) {
if (paired) { paired = true
self.doubleLinked = true
association.doubleLinked = true
self.targetAssociation = association
association.targetAssociation = self
}
} }
}) // If through is not default, determine pairing by through value (model/string)
if (self.through !== true && self.options.through === association.options.through) {
paired = true
}
// If paired, set properties identifying both associations as double linked, and allow them to each eachtoerh
if (paired) {
self.doubleLinked = true
association.doubleLinked = true
self.targetAssociation = association
association.targetAssociation = self
}
}
})
} }
/* /*
...@@ -90,13 +97,14 @@ module.exports = (function() { ...@@ -90,13 +97,14 @@ module.exports = (function() {
if (this.through === true) { if (this.through === true) {
this.through = this.combinedTableName this.through = this.combinedTableName
} }
if (typeof this.through === "string") { }
this.through = this.sequelize.define(this.through, {}, _.extend(this.options, {
tableName: this.through
}))
this.targetAssociation.through = this.through if (typeof this.through === "string") {
} this.through = this.sequelize.define(this.through, {}, _.extend(this.options, {
tableName: this.through
}))
if (this.targetAssociation) this.targetAssociation.through = this.through
} }
this.options.tableName = this.combinedName = (this.through === Object(this.through) ? this.through.tableName : this.through) this.options.tableName = this.combinedName = (this.through === Object(this.through) ? this.through.tableName : this.through)
...@@ -238,7 +246,7 @@ module.exports = (function() { ...@@ -238,7 +246,7 @@ module.exports = (function() {
return new Utils.CustomEventEmitter(function(emitter) { return new Utils.CustomEventEmitter(function(emitter) {
instance[self.accessors.get]() instance[self.accessors.get]()
.success(function(oldAssociatedObjects) { .success(function(oldAssociatedObjects) {
var Class = self.doubleLinked ? HasManyMultiLinked : HasManySingleLinked var Class = Object(self.through) === self.through ? HasManyMultiLinked : HasManySingleLinked
new Class(self, instance).injectSetter(emitter, oldAssociatedObjects, newAssociatedObjects, defaultAttributes) new Class(self, instance).injectSetter(emitter, oldAssociatedObjects, newAssociatedObjects, defaultAttributes)
}) })
.proxy(emitter, {events: ['error', 'sql']}) .proxy(emitter, {events: ['error', 'sql']})
...@@ -258,7 +266,7 @@ module.exports = (function() { ...@@ -258,7 +266,7 @@ module.exports = (function() {
.proxy(emitter, {events: ['error', 'sql']}) .proxy(emitter, {events: ['error', 'sql']})
.success(function(currentAssociatedObjects) { .success(function(currentAssociatedObjects) {
if (currentAssociatedObjects.length === 0 || Object(self.through) === self.through) { if (currentAssociatedObjects.length === 0 || Object(self.through) === self.through) {
var Class = self.doubleLinked ? HasManyMultiLinked : HasManySingleLinked var Class = Object(self.through) === self.through ? HasManyMultiLinked : HasManySingleLinked
new Class(self, instance).injectAdder(emitter, newAssociatedObject, additionalAttributes, !!currentAssociatedObjects.length) new Class(self, instance).injectAdder(emitter, newAssociatedObject, additionalAttributes, !!currentAssociatedObjects.length)
} else { } else {
emitter.emit('success', newAssociatedObject); emitter.emit('success', newAssociatedObject);
......
...@@ -1208,11 +1208,16 @@ module.exports = (function() { ...@@ -1208,11 +1208,16 @@ module.exports = (function() {
var validateIncludedElements = function(options) { var validateIncludedElements = function(options) {
options.includeNames = [] options.includeNames = []
options.includeMap = {} options.includeMap = {}
options.hasSingleAssociation = false
options.hasMultiAssociation = false
options.include = options.include.map(function(include) { options.include = options.include.map(function(include) {
include = validateIncludedElement.call(this, include, options.daoFactory) include = validateIncludedElement.call(this, include, options.daoFactory)
if (include.association.isMultiAssociation) options.hasMultiAssociation = true
if (include.association.isSingleAssociation) options.hasSingleAssociation = true
options.includeMap[include.as] = include options.includeMap[include.as] = include
options.includeNames.push(include.as) options.includeNames.push(include.as)
return include return include
}.bind(this)) }.bind(this))
}; };
......
...@@ -367,12 +367,19 @@ module.exports = (function() { ...@@ -367,12 +367,19 @@ module.exports = (function() {
options = options || {} options = options || {}
options.table = table = Array.isArray(tableName) ? tableName.map(function(t) { return this.quoteIdentifiers(t) }.bind(this)).join(", ") : this.quoteIdentifiers(tableName) options.table = table = Array.isArray(tableName) ? tableName.map(function(t) { return this.quoteIdentifiers(t) }.bind(this)).join(", ") : this.quoteIdentifiers(tableName)
options.attributes = options.attributes && options.attributes.map(function(attr){ options.attributes = options.attributes && options.attributes.map(function(attr){
if(Array.isArray(attr) && attr.length == 2) { if(Array.isArray(attr) && attr.length == 2) {
return [attr[0], this.quoteIdentifier(attr[1])].join(' as ') attr = [attr[0], this.quoteIdentifier(attr[1])].join(' as ')
} else { } else {
return attr.indexOf(Utils.TICK_CHAR) < 0 && attr.indexOf('"') < 0 ? this.quoteIdentifiers(attr) : attr attr = attr.indexOf(Utils.TICK_CHAR) < 0 && attr.indexOf('"') < 0 ? this.quoteIdentifiers(attr) : attr
}
if (options.include && attr.indexOf('.') === -1) {
attr = this.quoteIdentifier(options.table) + '.' + attr
} }
return attr
}.bind(this)).join(", ") }.bind(this)).join(", ")
options.attributes = options.attributes || '*' options.attributes = options.attributes || '*'
...@@ -392,7 +399,7 @@ module.exports = (function() { ...@@ -392,7 +399,7 @@ module.exports = (function() {
optAttributes = optAttributes.concat(attributes) optAttributes = optAttributes.concat(attributes)
if (include.association.doubleLinked) { if (Object(include.association.through) === include.association.through) {
var primaryKeysSource = Object.keys(include.association.source.primaryKeys) var primaryKeysSource = Object.keys(include.association.source.primaryKeys)
, tableSource = parentTable , tableSource = parentTable
, identSource = include.association.identifier , identSource = include.association.identifier
...@@ -437,7 +444,7 @@ module.exports = (function() { ...@@ -437,7 +444,7 @@ module.exports = (function() {
options.attributes = optAttributes.join(', ') options.attributes = optAttributes.join(', ')
} }
var conditionalJoins = this.getConditionalJoins(options, factory), var conditionalJoins = ((options.hasMultiAssociation && (options.limit || options.offset)) || !options.include) && this.getConditionalJoins(options, factory),
query; query;
if (conditionalJoins) { if (conditionalJoins) {
...@@ -449,7 +456,7 @@ module.exports = (function() { ...@@ -449,7 +456,7 @@ module.exports = (function() {
} }
if (options.hasOwnProperty('where')) { if (options.hasOwnProperty('where')) {
options.where = this.getWhereConditions(options.where, tableName, factory) options.where = this.getWhereConditions(options.where, tableName, factory, options)
query += " WHERE " + options.where query += " WHERE " + options.where
} }
...@@ -535,13 +542,13 @@ module.exports = (function() { ...@@ -535,13 +542,13 @@ module.exports = (function() {
/* /*
Takes something and transforms it into values of a where condition. Takes something and transforms it into values of a where condition.
*/ */
getWhereConditions: function(smth, tableName, factory) { getWhereConditions: function(smth, tableName, factory, options) {
var result = null var result = null
, where = {} , where = {}
if (Utils.isHash(smth)) { if (Utils.isHash(smth)) {
smth = Utils.prependTableNameToHash(tableName, smth) smth = Utils.prependTableNameToHash(tableName, smth)
result = this.hashToWhereConditions(smth, factory) result = this.hashToWhereConditions(smth, factory, options)
} else if (typeof smth === 'number') { } else if (typeof smth === 'number') {
var primaryKeys = !!factory ? Object.keys(factory.primaryKeys) : [] var primaryKeys = !!factory ? Object.keys(factory.primaryKeys) : []
if (primaryKeys.length > 0) { if (primaryKeys.length > 0) {
...@@ -601,7 +608,7 @@ module.exports = (function() { ...@@ -601,7 +608,7 @@ module.exports = (function() {
return dao; return dao;
}, },
isAssociationFilter: function(filterStr, dao){ isAssociationFilter: function(filterStr, dao, options){
if(!dao){ if(!dao){
return false; return false;
} }
...@@ -613,7 +620,6 @@ module.exports = (function() { ...@@ -613,7 +620,6 @@ module.exports = (function() {
, attributePart = associationParts.pop() , attributePart = associationParts.pop()
, self = this , self = this
return associationParts.every(function (attribute) { return associationParts.every(function (attribute) {
var association = self.findAssociation(attribute, dao); var association = self.findAssociation(attribute, dao);
if (!association) return false; if (!association) return false;
...@@ -622,16 +628,25 @@ module.exports = (function() { ...@@ -622,16 +628,25 @@ module.exports = (function() {
}) && dao.rawAttributes.hasOwnProperty(attributePart); }) && dao.rawAttributes.hasOwnProperty(attributePart);
}, },
getAssociationFilterColumn: function(filterStr, dao){ getAssociationFilterColumn: function(filterStr, dao, options){
var associationParts = filterStr.split('.') var associationParts = filterStr.split('.')
, attributePart = associationParts.pop() , attributePart = associationParts.pop()
, self = this , self = this
, association
, keyParts = []
associationParts.forEach(function (attribute) { associationParts.forEach(function (attribute) {
dao = self.findAssociation(attribute, dao).target; association = self.findAssociation(attribute, dao)
dao = association.target;
if (options.include) {
keyParts.push(association.as || association.options.as || dao.tableName)
}
}) })
return dao.tableName + '.' + attributePart; if (options.include) {
return this.quoteIdentifier(keyParts.join('.')) + '.' + this.quote(attributePart);
}
return this.quoteIdentifiers(dao.tableName + '.' + attributePart);
}, },
getConditionalJoins: function(options, originalDao){ getConditionalJoins: function(options, originalDao){
...@@ -645,7 +660,7 @@ module.exports = (function() { ...@@ -645,7 +660,7 @@ module.exports = (function() {
, attributePart = associationParts.pop() , attributePart = associationParts.pop()
, dao = originalDao , dao = originalDao
if (self.isAssociationFilter(filterStr, dao)) { if (self.isAssociationFilter(filterStr, dao, options)) {
associationParts.forEach(function (attribute) { associationParts.forEach(function (attribute) {
var association = self.findAssociation(attribute, dao); var association = self.findAssociation(attribute, dao);
...@@ -692,19 +707,21 @@ module.exports = (function() { ...@@ -692,19 +707,21 @@ module.exports = (function() {
Takes a hash and transforms it into a mysql where condition: {key: value, key2: value2} ==> key=value AND key2=value2 Takes a hash and transforms it into a mysql where condition: {key: value, key2: value2} ==> key=value AND key2=value2
The values are transformed by the relevant datatype. The values are transformed by the relevant datatype.
*/ */
hashToWhereConditions: function(hash, dao) { hashToWhereConditions: function(hash, dao, options) {
var result = [] var result = []
for (var key in hash) { for (var key in hash) {
var value = hash[key] var value = hash[key]
, _key
, _value = null
if(this.isAssociationFilter(key, dao)){ if(this.isAssociationFilter(key, dao, options)){
key = this.getAssociationFilterColumn(key, dao); _key = key = this.getAssociationFilterColumn(key, dao, options);
} else {
_key = this.quoteIdentifiers(key)
} }
//handle qualified key names //handle qualified key names
var _key = this.quoteIdentifiers(key)
, _value = null
if (Array.isArray(value)) { if (Array.isArray(value)) {
result.push(this.arrayValue(value, key, _key, dao)) result.push(this.arrayValue(value, key, _key, dao))
......
...@@ -429,6 +429,19 @@ describe(Support.getTestDialectTeaser("HasMany"), function() { ...@@ -429,6 +429,19 @@ describe(Support.getTestDialectTeaser("HasMany"), function() {
}) })
}) })
}) // end optimization using bulk create, destroy and update }) // end optimization using bulk create, destroy and update
describe('selfAssociations', function () {
it('should work', function (done) {
var Group = this.sequelize.define('Group', {})
Group.hasMany(Group, { through: 'groups_outsourcing_companies', as: 'OutsourcingCompanies'});
this.sequelize.sync().done(function (err) {
expect(err).not.to.be.ok
done()
})
})
})
}) })
describe('(N:M)', function() { describe('(N:M)', function() {
......
...@@ -18,7 +18,6 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() { ...@@ -18,7 +18,6 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() {
Task.belongsTo(Project); Task.belongsTo(Project);
Project.hasMany(Task); Project.hasMany(Task);
this.sequelize.sync({ force: true }).success(function() { this.sequelize.sync({ force: true }).success(function() {
User.bulkCreate([{ User.bulkCreate([{
username: 'leia' username: 'leia'
...@@ -47,8 +46,15 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() { ...@@ -47,8 +46,15 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() {
Task.findAll({ Task.findAll({
where: { where: {
'project.user.username': 'leia' 'project.user.username': 'leia'
} }/*,
}).success(function(tasks){ include: [
{model: Project, include: [
User
]}
]*/
}).done(function(err, tasks){
expect(err).not.to.be.ok
try{ try{
expect(tasks.length).to.be.equal(2); expect(tasks.length).to.be.equal(2);
expect(tasks[0].title).to.be.equal('fight empire'); expect(tasks[0].title).to.be.equal('fight empire');
...@@ -106,7 +112,12 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() { ...@@ -106,7 +112,12 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() {
where: { where: {
'project.user.username': 'leia', 'project.user.username': 'leia',
'project.user.id': 1 'project.user.id': 1
} }/*,
include: [
{model: Project, include: [
User
]}
]*/
}).success(function(tasks){ }).success(function(tasks){
try{ try{
expect(tasks.length).to.be.equal(2); expect(tasks.length).to.be.equal(2);
...@@ -134,7 +145,6 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() { ...@@ -134,7 +145,6 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() {
Task.belongsTo(Project); Task.belongsTo(Project);
Project.hasMany(Task); Project.hasMany(Task);
this.sequelize.sync({ force: true }).success(function() { this.sequelize.sync({ force: true }).success(function() {
User.bulkCreate([{ User.bulkCreate([{
username: 'leia' username: 'leia'
...@@ -164,8 +174,13 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() { ...@@ -164,8 +174,13 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() {
User.findAll({ User.findAll({
where: { where: {
'projects.tasks.title': 'fight empire' 'projects.tasks.title': 'fight empire'
} }/*,
}).success(function(users){ include: [
{model: Project, include: [
Task
]}
]*/
}).done(function(err, users){
try{ try{
expect(users.length).to.be.equal(1); expect(users.length).to.be.equal(1);
expect(users[0].username).to.be.equal('leia'); expect(users[0].username).to.be.equal('leia');
...@@ -208,7 +223,10 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() { ...@@ -208,7 +223,10 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() {
User.findAll({ User.findAll({
where: { where: {
'projects.title': 'republic' 'projects.title': 'republic'
} }/*,
include: [
{model: Project}
]*/
}).success(function(users){ }).success(function(users){
try{ try{
expect(users.length).to.be.equal(1); expect(users.length).to.be.equal(1);
......
...@@ -920,8 +920,8 @@ describe(Support.getTestDialectTeaser("DAO"), function () { ...@@ -920,8 +920,8 @@ describe(Support.getTestDialectTeaser("DAO"), function () {
overdue_days: DataTypes.INTEGER overdue_days: DataTypes.INTEGER
}, { timestamps: false }) }, { timestamps: false })
this.UserEager.hasMany(this.ProjectEager, { as: 'Projects' }) this.UserEager.hasMany(this.ProjectEager, { as: 'Projects' })
this.ProjectEager.belongsTo(this.UserEager, { as: 'Poobah' }) this.ProjectEager.belongsTo(this.UserEager, { as: 'Poobah' })
self.UserEager.sync({force: true}).success(function() { self.UserEager.sync({force: true}).success(function() {
self.ProjectEager.sync({force: true}).success(function() { self.ProjectEager.sync({force: true}).success(function() {
...@@ -1016,7 +1016,6 @@ describe(Support.getTestDialectTeaser("DAO"), function () { ...@@ -1016,7 +1016,6 @@ describe(Support.getTestDialectTeaser("DAO"), function () {
self.ProjectEager.create({ title: 'party', overdue_days: 2 }).success(function(party) { self.ProjectEager.create({ title: 'party', overdue_days: 2 }).success(function(party) {
user.setProjects([homework, party]).success(function() { user.setProjects([homework, party]).success(function() {
self.ProjectEager.findAll({include: [{model: self.UserEager, as: 'Poobah'}]}).success(function(projects) { self.ProjectEager.findAll({include: [{model: self.UserEager, as: 'Poobah'}]}).success(function(projects) {
expect(projects.length).to.equal(2) expect(projects.length).to.equal(2)
expect(projects[0].poobah).to.exist expect(projects[0].poobah).to.exist
expect(projects[1].poobah).to.exist expect(projects[1].poobah).to.exist
......
...@@ -288,7 +288,7 @@ describe(Support.getTestDialectTeaser("Include"), function () { ...@@ -288,7 +288,7 @@ describe(Support.getTestDialectTeaser("Include"), function () {
]} ]}
] ]
}).done(function (err, user) { }).done(function (err, user) {
expect(err).not.to.be.ok expect(err).not.to.be.ok
expect(user.products.length).to.equal(4) expect(user.products.length).to.equal(4)
expect(user.products[0].tags.length).to.equal(2) expect(user.products[0].tags.length).to.equal(2)
...@@ -454,6 +454,64 @@ describe(Support.getTestDialectTeaser("Include"), function () { ...@@ -454,6 +454,64 @@ describe(Support.getTestDialectTeaser("Include"), function () {
}) })
}) })
}) })
it('should support specifying attributes', function (done) {
var Project = this.sequelize.define('Project', {
title: Sequelize.STRING
})
var Task = this.sequelize.define('Task', {
title: Sequelize.STRING,
description: Sequelize.TEXT
})
Project.hasMany(Task)
Task.belongsTo(Project)
this.sequelize.sync().done(function() {
Task.create({title: 'FooBar'}).done(function (err) {
Task.findAll({attributes: ['title'], include: [Project]}).done(function(err, tasks) {
expect(err).not.to.be.ok
expect(tasks[0].title).to.equal('FooBar')
done()
})
})
})
})
it('should support self associated hasMany (with through) include', function (done) {
var Group = this.sequelize.define('Group', {
name: DataTypes.STRING
})
Group.hasMany(Group, { through: 'groups_outsourcing_companies', as: 'OutsourcingCompanies'});
this.sequelize.sync().done(function (err) {
Group.bulkCreate([
{name: 'SoccerMoms'},
{name: 'Coca Cola'},
{name: 'Dell'},
{name: 'Pepsi'}
]).done(function () {
Group.findAll().done(function (err, groups) {
groups[0].setOutsourcingCompanies(groups.slice(1)).done(function (err) {
expect(err).not.to.be.ok
Group.find({
where: {
id: groups[0].id,
},
include: [{model: Group, as: 'OutsourcingCompanies'}]
}).done(function (err, group) {
expect(err).not.to.be.ok
expect(group.outsourcingCompanies.length).to.equal(3)
done()
})
})
})
})
})
})
}) })
describe('findAll', function () { describe('findAll', function () {
...@@ -608,7 +666,7 @@ describe(Support.getTestDialectTeaser("Include"), function () { ...@@ -608,7 +666,7 @@ describe(Support.getTestDialectTeaser("Include"), function () {
Tag, Tag,
{model: Tag, as: 'Category'}, {model: Tag, as: 'Category'},
Price Price
]} ]}
], ],
order: 'id ASC' order: 'id ASC'
}).done(function (err, users) { }).done(function (err, users) {
...@@ -742,5 +800,94 @@ describe(Support.getTestDialectTeaser("Include"), function () { ...@@ -742,5 +800,94 @@ describe(Support.getTestDialectTeaser("Include"), function () {
}) })
}) })
}) })
it('should support ordering with only belongsTo includes', function(done) {
var User = this.sequelize.define('User', {})
, Item = this.sequelize.define('Item', {'test': DataTypes.STRING})
, Order = this.sequelize.define('Order', {'position': DataTypes.INTEGER})
User.belongsTo(Item, {'as': 'itemA', foreignKey: 'itemA_id'})
User.belongsTo(Item, {'as': 'itemB', foreignKey: 'itemB_id'})
User.belongsTo(Order)
this.sequelize.sync().done(function() {
async.auto({
users: function(callback) {
User.bulkCreate([{}, {}, {}]).done(function() {
User.findAll().done(callback)
})
},
items: function(callback) {
Item.bulkCreate([
{'test': 'abc'},
{'test': 'def'},
{'test': 'ghi'},
{'test': 'jkl'}
]).done(function() {
Item.findAll({order: ['id']}).done(callback)
})
},
orders: function(callback) {
Order.bulkCreate([
{'position': 2},
{'position': 3},
{'position': 1}
]).done(function() {
Order.findAll({order: ['id']}).done(callback)
})
},
associate: ['users', 'items', 'orders', function(callback, results) {
var chainer = new Sequelize.Utils.QueryChainer()
var user1 = results.users[0]
var user2 = results.users[1]
var user3 = results.users[2]
var item1 = results.items[0]
var item2 = results.items[1]
var item3 = results.items[2]
var item4 = results.items[3]
var order1 = results.orders[0]
var order2 = results.orders[1]
var order3 = results.orders[2]
chainer.add(user1.setItemA(item1))
chainer.add(user1.setItemB(item2))
chainer.add(user1.setOrder(order3))
chainer.add(user2.setItemA(item3))
chainer.add(user2.setItemB(item4))
chainer.add(user2.setOrder(order2))
chainer.add(user3.setItemA(item1))
chainer.add(user3.setItemB(item4))
chainer.add(user3.setOrder(order1))
chainer.run().done(callback)
}]
}, function() {
User.findAll({
'where': {'itemA.test': 'abc'},
'include': [
{'model': Item, 'as': 'itemA'},
{'model': Item, 'as': 'itemB'},
Order],
'order': ['Order.position']
}).done(function(err, as) {
expect(err).not.to.be.ok
expect(as.length).to.eql(2)
expect(as[0].itemA.test).to.eql('abc')
expect(as[1].itemA.test).to.eql('abc')
expect(as[0].order.position).to.eql(1)
expect(as[1].order.position).to.eql(2)
done()
})
})
})
})
}) })
}) })
\ 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!