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

Commit cdf00c41 by tornillo

Association mixins refactoring

Fix es6 syntax, docs and changelog
1 parent 95d3a571
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
- [FIXED] Issue with query generation in MSSQL, an identifier was not escaped [#6686] (https://github.com/sequelize/sequelize/pull/6686) - [FIXED] Issue with query generation in MSSQL, an identifier was not escaped [#6686] (https://github.com/sequelize/sequelize/pull/6686)
- [FIXED] GroupedLimit when foreignKey has a field alias - [FIXED] GroupedLimit when foreignKey has a field alias
- [FIXED] groupedLimit.through.where support - [FIXED] groupedLimit.through.where support
- [FIXED] Issue with overrriding custom methods with association mixins (all association methods are now exposed) [#6682](https://github.com/sequelize/sequelize/issues/6682)
# 4.0.0-2 # 4.0.0-2
- [ADDED] include now supports string as an argument (on top of model/association), string will expand into an association matched literally from Model.associations - [ADDED] include now supports string as an argument (on top of model/association), string will expand into an association matched literally from Model.associations
......
...@@ -444,6 +444,18 @@ class BelongsToMany extends Association { ...@@ -444,6 +444,18 @@ class BelongsToMany extends Association {
return this; return this;
} }
mixin(obj) {
const methods = ['get', 'count', 'hasSingle', 'hasAll', 'set', 'add', 'addMultiple', 'remove', 'removeMultiple', 'create'];
const aliases = {
hasSingle: 'has',
hasAll: 'has',
addMultiple: 'add',
removeMultiple: 'remove'
};
Helpers.mixinMethods(this, obj, methods, aliases);
}
get(instance, options) { get(instance, options) {
options = Utils.cloneDeep(options) || {}; options = Utils.cloneDeep(options) || {};
...@@ -503,14 +515,8 @@ class BelongsToMany extends Association { ...@@ -503,14 +515,8 @@ class BelongsToMany extends Association {
return model.findAll(options); return model.findAll(options);
} }
injectGetter(obj) { count(instance, options) {
const association = this; const association = this;
obj[this.accessors.get] = function(options) {
return association.get(this, options);
};
obj[this.accessors.count] = function(options) {
const model = association.target; const model = association.target;
const sequelize = model.sequelize; const sequelize = model.sequelize;
...@@ -522,10 +528,11 @@ class BelongsToMany extends Association { ...@@ -522,10 +528,11 @@ class BelongsToMany extends Association {
options.raw = true; options.raw = true;
options.plain = true; options.plain = true;
return obj[association.accessors.get].call(this, options).then(result => parseInt(result.count, 10)); return association.get(instance, options).then(result => parseInt(result.count, 10));
}; }
obj[this.accessors.hasSingle] = obj[this.accessors.hasAll] = function(instances, options) { has(sourceInstance, instances, options) {
const association = this;
const where = {}; const where = {};
if (!Array.isArray(instances)) { if (!Array.isArray(instances)) {
...@@ -555,17 +562,13 @@ class BelongsToMany extends Association { ...@@ -555,17 +562,13 @@ class BelongsToMany extends Association {
] ]
}; };
return this[association.accessors.get](options).then(associatedObjects => associatedObjects.length === instances.length); return association.get(sourceInstance, options).then(associatedObjects => associatedObjects.length === instances.length);
};
return this;
} }
injectSetter(obj) { set(sourceInstance, newAssociatedObjects, options) {
const association = this;
obj[this.accessors.set] = function(newAssociatedObjects, options) {
options = options || {}; options = options || {};
const association = this;
const sourceKey = association.source.primaryKeyAttribute; const sourceKey = association.source.primaryKeyAttribute;
const targetKey = association.target.primaryKeyAttribute; const targetKey = association.target.primaryKeyAttribute;
const identifier = association.identifier; const identifier = association.identifier;
...@@ -578,7 +581,7 @@ class BelongsToMany extends Association { ...@@ -578,7 +581,7 @@ class BelongsToMany extends Association {
newAssociatedObjects = association.toInstanceArray(newAssociatedObjects); newAssociatedObjects = association.toInstanceArray(newAssociatedObjects);
} }
where[identifier] = this.get(sourceKey); where[identifier] = sourceInstance.get(sourceKey);
return association.through.model.findAll(_.defaults({where, raw: true}, options)).then(currentRows => { return association.through.model.findAll(_.defaults({where, raw: true}, options)).then(currentRows => {
const obsoleteAssociations = []; const obsoleteAssociations = [];
const promises = []; const promises = [];
...@@ -606,7 +609,7 @@ class BelongsToMany extends Association { ...@@ -606,7 +609,7 @@ class BelongsToMany extends Association {
const where = {}; const where = {};
const attributes = _.defaults({}, throughAttributes, defaultAttributes); const attributes = _.defaults({}, throughAttributes, defaultAttributes);
where[identifier] = this.get(sourceKey); where[identifier] = sourceInstance.get(sourceKey);
where[foreignIdentifier] = newObj.get(targetKey); where[foreignIdentifier] = newObj.get(targetKey);
if (Object.keys(attributes).length) { if (Object.keys(attributes).length) {
...@@ -617,7 +620,7 @@ class BelongsToMany extends Association { ...@@ -617,7 +620,7 @@ class BelongsToMany extends Association {
if (obsoleteAssociations.length > 0) { if (obsoleteAssociations.length > 0) {
const where = {}; const where = {};
where[identifier] = this.get(sourceKey); where[identifier] = sourceInstance.get(sourceKey);
where[foreignIdentifier] = obsoleteAssociations.map(obsoleteAssociation => obsoleteAssociation[foreignIdentifier]); where[foreignIdentifier] = obsoleteAssociations.map(obsoleteAssociation => obsoleteAssociation[foreignIdentifier]);
promises.push(association.through.model.destroy(_.defaults({where}, options))); promises.push(association.through.model.destroy(_.defaults({where}, options)));
...@@ -627,7 +630,7 @@ class BelongsToMany extends Association { ...@@ -627,7 +630,7 @@ class BelongsToMany extends Association {
const bulk = unassociatedObjects.map(unassociatedObject => { const bulk = unassociatedObjects.map(unassociatedObject => {
let attributes = {}; let attributes = {};
attributes[identifier] = this.get(sourceKey); attributes[identifier] = sourceInstance.get(sourceKey);
attributes[foreignIdentifier] = unassociatedObject.get(targetKey); attributes[foreignIdentifier] = unassociatedObject.get(targetKey);
attributes = _.defaults(attributes, unassociatedObject[association.through.model.name], defaultAttributes); attributes = _.defaults(attributes, unassociatedObject[association.through.model.name], defaultAttributes);
...@@ -642,14 +645,15 @@ class BelongsToMany extends Association { ...@@ -642,14 +645,15 @@ class BelongsToMany extends Association {
return Utils.Promise.all(promises); return Utils.Promise.all(promises);
}); });
}; }
obj[this.accessors.addMultiple] = obj[this.accessors.add] = function(newInstances, additionalAttributes) { add(sourceInstance, newInstances, additionalAttributes) {
// If newInstances is null or undefined, no-op // If newInstances is null or undefined, no-op
if (!newInstances) return Utils.Promise.resolve(); if (!newInstances) return Utils.Promise.resolve();
additionalAttributes = _.clone(additionalAttributes) || {}; additionalAttributes = _.clone(additionalAttributes) || {};
const association = this;
const defaultAttributes = _.omit(additionalAttributes, ['transaction', 'hooks', 'individualHooks', 'ignoreDuplicates', 'validate', 'fields', 'logging']); const defaultAttributes = _.omit(additionalAttributes, ['transaction', 'hooks', 'individualHooks', 'ignoreDuplicates', 'validate', 'fields', 'logging']);
const sourceKey = association.source.primaryKeyAttribute; const sourceKey = association.source.primaryKeyAttribute;
const targetKey = association.target.primaryKeyAttribute; const targetKey = association.target.primaryKeyAttribute;
...@@ -660,7 +664,7 @@ class BelongsToMany extends Association { ...@@ -660,7 +664,7 @@ class BelongsToMany extends Association {
newInstances = association.toInstanceArray(newInstances); newInstances = association.toInstanceArray(newInstances);
const where = {}; const where = {};
where[identifier] = this.get(sourceKey); where[identifier] = sourceInstance.get(sourceKey);
where[foreignIdentifier] = newInstances.map(newInstance => newInstance.get(targetKey)); where[foreignIdentifier] = newInstances.map(newInstance => newInstance.get(targetKey));
_.assign(where, association.through.scope); _.assign(where, association.through.scope);
...@@ -689,7 +693,7 @@ class BelongsToMany extends Association { ...@@ -689,7 +693,7 @@ class BelongsToMany extends Association {
const throughAttributes = unassociatedObject[association.through.model.name]; const throughAttributes = unassociatedObject[association.through.model.name];
const attributes = _.defaults({}, throughAttributes, defaultAttributes); const attributes = _.defaults({}, throughAttributes, defaultAttributes);
attributes[identifier] = this.get(sourceKey); attributes[identifier] = sourceInstance.get(sourceKey);
attributes[foreignIdentifier] = unassociatedObject.get(targetKey); attributes[foreignIdentifier] = unassociatedObject.get(targetKey);
_.assign(attributes, association.through.scope); _.assign(attributes, association.through.scope);
...@@ -709,7 +713,7 @@ class BelongsToMany extends Association { ...@@ -709,7 +713,7 @@ class BelongsToMany extends Association {
throughAttributes = {}; throughAttributes = {};
} }
where[identifier] = this.get(sourceKey); where[identifier] = sourceInstance.get(sourceKey);
where[foreignIdentifier] = assoc.get(targetKey); where[foreignIdentifier] = assoc.get(targetKey);
promises.push(association.through.model.update(attributes, _.extend(options, {where}))); promises.push(association.through.model.update(attributes, _.extend(options, {where})));
...@@ -717,27 +721,25 @@ class BelongsToMany extends Association { ...@@ -717,27 +721,25 @@ class BelongsToMany extends Association {
return Utils.Promise.all(promises); return Utils.Promise.all(promises);
}); });
}; }
remove(sourceInstance, oldAssociatedObjects, options) {
const association = this;
obj[this.accessors.removeMultiple] = obj[this.accessors.remove] = function(oldAssociatedObjects, options) {
options = options || {}; options = options || {};
oldAssociatedObjects = association.toInstanceArray(oldAssociatedObjects); oldAssociatedObjects = association.toInstanceArray(oldAssociatedObjects);
const where = {}; const where = {};
where[association.identifier] = this.get(association.source.primaryKeyAttribute); where[association.identifier] = sourceInstance.get(association.source.primaryKeyAttribute);
where[association.foreignIdentifier] = oldAssociatedObjects.map(newInstance => newInstance.get(association.target.primaryKeyAttribute)); where[association.foreignIdentifier] = oldAssociatedObjects.map(newInstance => newInstance.get(association.target.primaryKeyAttribute));
return association.through.model.destroy(_.defaults({where}, options)); return association.through.model.destroy(_.defaults({where}, options));
};
return this;
} }
injectCreator(obj) { create(sourceInstance, values, options) {
const association = this; const association = this;
obj[this.accessors.create] = function(values, options) {
options = options || {}; options = options || {};
values = values || {}; values = values || {};
...@@ -756,11 +758,8 @@ class BelongsToMany extends Association { ...@@ -756,11 +758,8 @@ class BelongsToMany extends Association {
// Create the related model instance // Create the related model instance
return association.target.create(values, options).then(newAssociatedObject => return association.target.create(values, options).then(newAssociatedObject =>
this[association.accessors.add](newAssociatedObject, _.omit(options, ['fields'])).return(newAssociatedObject) sourceInstance[association.accessors.add](newAssociatedObject, _.omit(options, ['fields'])).return(newAssociatedObject)
); );
};
return this;
} }
} }
......
...@@ -140,14 +140,9 @@ class BelongsTo extends Association { ...@@ -140,14 +140,9 @@ class BelongsTo extends Association {
} }
mixin(obj) { mixin(obj) {
const association = this; const methods = ['get', 'set', 'create'];
obj[this.accessors.get] = function(options) {
return association.get(this, options);
};
association.injectSetter(obj); Helpers.mixinMethods(this, obj, methods);
association.injectCreator(obj);
} }
get(instances, options) { get(instances, options) {
...@@ -206,14 +201,13 @@ class BelongsTo extends Association { ...@@ -206,14 +201,13 @@ class BelongsTo extends Association {
return result; return result;
}); });
} }
return Target.findOne(options); return Target.findOne(options);
} }
// Add setAssociation method to the prototype of the model instance set(sourceInstance, associatedInstance, options) {
injectSetter(instancePrototype) {
const association = this; const association = this;
instancePrototype[this.accessors.set] = function(associatedInstance, options) {
options = options || {}; options = options || {};
let value = associatedInstance; let value = associatedInstance;
...@@ -221,7 +215,7 @@ class BelongsTo extends Association { ...@@ -221,7 +215,7 @@ class BelongsTo extends Association {
value = associatedInstance[association.targetKey]; value = associatedInstance[association.targetKey];
} }
this.set(association.foreignKey, value); sourceInstance.set(association.foreignKey, value);
if (options.save === false) return; if (options.save === false) return;
...@@ -231,19 +225,13 @@ class BelongsTo extends Association { ...@@ -231,19 +225,13 @@ class BelongsTo extends Association {
association: true association: true
}, options); }, options);
// passes the changed field to save, so only that field get updated. // passes the changed field to save, so only that field get updated.
return this.save(options); return sourceInstance.save(options);
};
return this;
} }
// Add createAssociation method to the prototype of the model instance create(sourceInstance, values, fieldsOrOptions) {
injectCreator(instancePrototype) {
const association = this; const association = this;
instancePrototype[this.accessors.create] = function(values, fieldsOrOptions) {
const options = {}; const options = {};
if ((fieldsOrOptions || {}).transaction instanceof Transaction) { if ((fieldsOrOptions || {}).transaction instanceof Transaction) {
...@@ -252,11 +240,8 @@ class BelongsTo extends Association { ...@@ -252,11 +240,8 @@ class BelongsTo extends Association {
options.logging = (fieldsOrOptions || {}).logging; options.logging = (fieldsOrOptions || {}).logging;
return association.target.create(values, fieldsOrOptions).then(newAssociatedObject => return association.target.create(values, fieldsOrOptions).then(newAssociatedObject =>
this[association.accessors.set](newAssociatedObject, options) sourceInstance[association.accessors.set](newAssociatedObject, options)
); );
};
return this;
} }
} }
......
...@@ -233,37 +233,15 @@ class HasMany extends Association { ...@@ -233,37 +233,15 @@ class HasMany extends Association {
} }
mixin(obj) { mixin(obj) {
const association = this; const methods = ['get', 'count', 'hasSingle', 'hasAll', 'set', 'add', 'addMultiple', 'remove', 'removeMultiple', 'create'];
const aliases = {
obj[this.accessors.get] = function(options) { hasSingle: 'has',
return association.get(this, options); hasAll: 'has',
}; addMultiple: 'add',
removeMultiple: 'remove'
if (this.accessors.count) {
obj[this.accessors.count] = function(options) {
return association.count(this, options);
};
}
obj[this.accessors.hasSingle] = obj[this.accessors.hasAll] = function(instances, options) {
return association.has(this, instances, options);
}; };
obj[this.accessors.set] = function(instances, options) { Helpers.mixinMethods(this, obj, methods, aliases);
return association.set(this, instances, options);
};
obj[this.accessors.add] = obj[this.accessors.addMultiple] = function(instances, options) {
return association.add(this, instances, options);
};
obj[this.accessors.remove] = obj[this.accessors.removeMultiple] = function(instances, options) {
return association.remove(this, instances, options);
};
obj[this.accessors.create] = function(values, options) {
return association.create(this, values, options);
};
} }
get(instances, options) { get(instances, options) {
...@@ -351,7 +329,7 @@ class HasMany extends Association { ...@@ -351,7 +329,7 @@ class HasMany extends Association {
options.raw = true; options.raw = true;
options.plain = true; options.plain = true;
return this.get(instance, options).then(result => parseInt(result.count, 10)); return association.get(instance, options).then(result => parseInt(result.count, 10));
} }
has(sourceInstance, targetInstances, options) { has(sourceInstance, targetInstances, options) {
...@@ -384,7 +362,7 @@ class HasMany extends Association { ...@@ -384,7 +362,7 @@ class HasMany extends Association {
] ]
}; };
return this.get(sourceInstance, options).then(associatedObjects => associatedObjects.length === targetInstances.length); return association.get(sourceInstance, options).then(associatedObjects => associatedObjects.length === targetInstances.length);
} }
set(sourceInstance, targetInstances, options) { set(sourceInstance, targetInstances, options) {
......
...@@ -138,14 +138,9 @@ class HasOne extends Association { ...@@ -138,14 +138,9 @@ class HasOne extends Association {
} }
mixin(obj) { mixin(obj) {
const association = this; const methods = ['get', 'set', 'create'];
obj[this.accessors.get] = function(options) {
return association.get(this, options);
};
association.injectSetter(obj); Helpers.mixinMethods(this, obj, methods);
association.injectCreator(obj);
} }
get(instances, options) { get(instances, options) {
...@@ -206,16 +201,16 @@ class HasOne extends Association { ...@@ -206,16 +201,16 @@ class HasOne extends Association {
return Target.findOne(options); return Target.findOne(options);
} }
injectSetter(instancePrototype) { set(sourceInstance, associatedInstance, options) {
const association = this; const association = this;
instancePrototype[this.accessors.set] = function(associatedInstance, options) {
let alreadyAssociated; let alreadyAssociated;
options = _.assign({}, options, { options = _.assign({}, options, {
scope: false scope: false
}); });
return this[association.accessors.get](options).then(oldInstance => {
return sourceInstance[association.accessors.get](options).then(oldInstance => {
// TODO Use equals method once #5605 is resolved // TODO Use equals method once #5605 is resolved
alreadyAssociated = oldInstance && associatedInstance && _.every(association.target.primaryKeyAttributes, attribute => alreadyAssociated = oldInstance && associatedInstance && _.every(association.target.primaryKeyAttributes, attribute =>
oldInstance.get(attribute, {raw: true}) === (associatedInstance.get ? associatedInstance.get(attribute, {raw: true}) : associatedInstance) oldInstance.get(attribute, {raw: true}) === (associatedInstance.get ? associatedInstance.get(attribute, {raw: true}) : associatedInstance)
...@@ -240,37 +235,36 @@ class HasOne extends Association { ...@@ -240,37 +235,36 @@ class HasOne extends Association {
} }
_.assign(associatedInstance, association.scope); _.assign(associatedInstance, association.scope);
associatedInstance.set(association.foreignKey, this.get(association.sourceIdentifier)); associatedInstance.set(association.foreignKey, sourceInstance.get(association.sourceIdentifier));
return associatedInstance.save(options); return associatedInstance.save(options);
} }
return null; return null;
}); });
};
return this;
} }
injectCreator(instancePrototype) { create(sourceInstance, values, options) {
const association = this; const association = this;
instancePrototype[this.accessors.create] = function(values, options) {
values = values || {}; values = values || {};
options = options || {}; options = options || {};
if (association.scope) { if (association.scope) {
for (const attribute of Object.keys(association.scope)) { for (const attribute of Object.keys(association.scope)) {
values[attribute] = association.scope[attribute]; values[attribute] = association.scope[attribute];
if (options.fields) options.fields.push(attribute); if (options.fields) {
options.fields.push(attribute);
}
} }
} }
values[association.foreignKey] = this.get(association.sourceIdentifier); values[association.foreignKey] = sourceInstance.get(association.sourceIdentifier);
if (options.fields) options.fields.push(association.foreignKey); if (options.fields) {
return association.target.create(values, options); options.fields.push(association.foreignKey);
}; }
return this; return association.target.create(values, options);
} }
} }
......
...@@ -44,3 +44,30 @@ function addForeignKeyConstraints(newAttribute, source, target, options, key) { ...@@ -44,3 +44,30 @@ function addForeignKeyConstraints(newAttribute, source, target, options, key) {
} }
} }
exports.addForeignKeyConstraints = addForeignKeyConstraints; exports.addForeignKeyConstraints = addForeignKeyConstraints;
/**
* Mixin (inject) association methods to model prototype
*
* @param {Object} Association instance
* @param {Object} Model prototype
* @param {Array} Method names to inject
* @param {Object} Mapping between model and association method names
*/
function mixinMethods(association, obj, methods, aliases) {
aliases = aliases || {};
for (const method of methods) {
// don't override custom methods
if (!obj[association.accessors[method]]) {
const realMethod = aliases[method] || method;
obj[association.accessors[method]] = function() {
const instance = this;
const args = [instance].concat(Array.from(arguments));
return association[realMethod].apply(association, args);
};
}
}
}
exports.mixinMethods = mixinMethods;
...@@ -201,11 +201,10 @@ const Mixin = { ...@@ -201,11 +201,10 @@ const Mixin = {
// the id is in the foreign table or in a connecting table // the id is in the foreign table or in a connecting table
const association = new BelongsToMany(sourceModel, targetModel, options); const association = new BelongsToMany(sourceModel, targetModel, options);
sourceModel.associations[association.associationAccessor] = association.injectAttributes(); sourceModel.associations[association.associationAccessor] = association;
association.injectGetter(sourceModel.prototype); association.injectAttributes();
association.injectSetter(sourceModel.prototype); association.mixin(sourceModel.prototype);
association.injectCreator(sourceModel.prototype);
return association; return association;
}, },
...@@ -241,15 +240,10 @@ function singleLinked(Type) { ...@@ -241,15 +240,10 @@ function singleLinked(Type) {
// the id is in the foreign table // the id is in the foreign table
const association = new Type(source, target, _.extend(options, source.options)); const association = new Type(source, target, _.extend(options, source.options));
source.associations[association.associationAccessor] = association.injectAttributes(); source.associations[association.associationAccessor] = association;
if (association.mixin) { association.injectAttributes();
association.mixin(source.prototype); association.mixin(source.prototype);
} else {
association.injectGetter(source.prototype);
association.injectSetter(source.prototype);
association.injectCreator(source.prototype);
}
return association; return association;
}; };
......
...@@ -58,6 +58,39 @@ describe(Support.getTestDialectTeaser('belongsToMany'), function() { ...@@ -58,6 +58,39 @@ describe(Support.getTestDialectTeaser('belongsToMany'), function() {
expect(AB.options.validate).to.deep.equal({}); expect(AB.options.validate).to.deep.equal({});
}); });
it('should not override custom methods with association mixin', function(){
const methods = {
getTasks: 'get',
countTasks: 'count',
hasTask: 'has',
hasTasks: 'has',
setTasks: 'set',
addTask: 'add',
addTasks: 'add',
removeTask: 'remove',
removeTasks: 'remove',
createTask: 'create',
};
const User = current.define('User');
const Task = current.define('Task');
current.Utils._.each(methods, (alias, method) => {
User.prototype[method] = function () {
const realMethod = this.constructor.associations.task[alias];
expect(realMethod).to.be.a('function');
return realMethod;
};
});
User.belongsToMany(Task, { through: 'UserTasks', as: 'task' });
const user = User.build();
current.Utils._.each(methods, (alias, method) => {
expect(user[method]()).to.be.a('function');
});
});
describe('timestamps', function () { describe('timestamps', function () {
it('follows the global timestamps true option', function () { it('follows the global timestamps true option', function () {
var User = current.define('User', {}) var User = current.define('User', {})
......
'use strict';
/* jshint -W030 */
var chai = require('chai')
, expect = chai.expect
, Support = require(__dirname + '/../support')
, current = Support.sequelize;
describe(Support.getTestDialectTeaser('belongsTo'), function() {
it('should not override custom methods with association mixin', function(){
const methods = {
getTask : 'get',
setTask: 'set',
createTask: 'create'
};
const User = current.define('User');
const Task = current.define('Task');
current.Utils._.each(methods, (alias, method) => {
User.prototype[method] = function () {
const realMethod = this.constructor.associations.task[alias];
expect(realMethod).to.be.a('function');
return realMethod;
};
});
User.belongsTo(Task, { as: 'task' });
const user = User.build();
current.Utils._.each(methods, (alias, method) => {
expect(user[method]()).to.be.a('function');
});
});
});
...@@ -84,6 +84,37 @@ describe(Support.getTestDialectTeaser('hasMany'), function() { ...@@ -84,6 +84,37 @@ describe(Support.getTestDialectTeaser('hasMany'), function() {
expect(obj[association.accessors.hasAll]).to.be.an('function'); expect(obj[association.accessors.hasAll]).to.be.an('function');
expect(obj[association.accessors.count]).to.be.an('function'); expect(obj[association.accessors.count]).to.be.an('function');
}); });
it('should not override custom methods', function(){
const methods = {
getTasks: 'get',
countTasks: 'count',
hasTask: 'has',
hasTasks: 'has',
setTasks: 'set',
addTask: 'add',
addTasks: 'add',
removeTask: 'remove',
removeTasks: 'remove',
createTask: 'create',
};
current.Utils._.each(methods, (alias, method) => {
User.prototype[method] = function () {
const realMethod = this.constructor.associations.task[alias];
expect(realMethod).to.be.a('function');
return realMethod;
};
});
User.hasMany(Task, { as: 'task' });
const user = User.build();
current.Utils._.each(methods, (alias, method) => {
expect(user[method]()).to.be.a('function');
});
});
}); });
describe('get', function () { describe('get', function () {
......
...@@ -18,4 +18,30 @@ describe(Support.getTestDialectTeaser('hasOne'), function() { ...@@ -18,4 +18,30 @@ describe(Support.getTestDialectTeaser('hasOne'), function() {
User.hasOne(Task, {as : 'Shabda'}); User.hasOne(Task, {as : 'Shabda'});
expect(Task.attributes.ShabdaId).not.to.be.empty; expect(Task.attributes.ShabdaId).not.to.be.empty;
}); });
it('should not override custom methods with association mixin', function(){
const methods = {
getTask : 'get',
setTask: 'set',
createTask: 'create'
};
const User = current.define('User');
const Task = current.define('Task');
current.Utils._.each(methods, (alias, method) => {
User.prototype[method] = function () {
const realMethod = this.constructor.associations.task[alias];
expect(realMethod).to.be.a('function');
return realMethod;
};
});
User.hasOne(Task, { as: 'task' });
const user = User.build();
current.Utils._.each(methods, (alias, method) => {
expect(user[method]()).to.be.a('function');
});
});
}); });
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!