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

Commit 32be0612 by Scott BonAmi Committed by Simon Schick

fix(associations): check presence of multi-joined instances (#10853)

When entities in a HABTM relationship can be joined more than once, we
need to rely on more than the resulting length for verification of
presence.
1 parent 04e3592e
......@@ -466,8 +466,6 @@ class BelongsToMany extends Association {
* @returns {Promise<boolean>}
*/
has(sourceInstance, instances, options) {
const where = {};
if (!Array.isArray(instances)) {
instances = [instances];
}
......@@ -480,7 +478,7 @@ class BelongsToMany extends Association {
joinTableAttributes: []
});
where[Op.or] = instances.map(instance => {
const instancePrimaryKeys = instances.map(instance => {
if (instance instanceof this.target) {
return instance.where();
}
......@@ -491,12 +489,14 @@ class BelongsToMany extends Association {
options.where = {
[Op.and]: [
where,
{ [Op.or]: instancePrimaryKeys },
options.where
]
};
return this.get(sourceInstance, options).then(associatedObjects => associatedObjects.length === instances.length);
return this.get(sourceInstance, options).then(associatedObjects =>
_.differenceBy(instancePrimaryKeys, associatedObjects, this.target.primaryKeyAttribute).length === 0
);
}
/**
......
......@@ -556,6 +556,93 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), () => {
});
});
});
it('answers true for labels that have been assigned multitple times', function() {
this.ArticleLabel = this.sequelize.define('ArticleLabel', {
id: {
primaryKey: true,
type: DataTypes.INTEGER,
autoIncrement: true
},
relevance: {
type: DataTypes.DECIMAL,
validate: {
min: 0,
max: 1
}
}
});
this.Article.belongsToMany(this.Label, { through: { model: this.ArticleLabel, unique: false } });
this.Label.belongsToMany(this.Article, { through: { model: this.ArticleLabel, unique: false } });
return this.sequelize.sync({ force: true })
.then(() => Promise.all([
this.Article.create({ title: 'Article' }),
this.Label.create({ text: 'Awesomeness' }),
this.Label.create({ text: 'Epicness' })
]))
.then(([article, label1, label2]) => Promise.all([
article,
label1,
label2,
article.addLabel(label1, {
through: { relevance: 1 }
}),
article.addLabel(label2, {
through: { relevance: .54 }
}),
article.addLabel(label2, {
through: { relevance: .99 }
})
]))
.then(([article, label1, label2]) => article.hasLabels([label1, label2]))
.then(result => expect(result).to.be.true);
});
it('answers true for labels that have been assigned multitple times when passing a primary key instead of an object', function() {
this.ArticleLabel = this.sequelize.define('ArticleLabel', {
id: {
primaryKey: true,
type: DataTypes.INTEGER,
autoIncrement: true
},
relevance: {
type: DataTypes.DECIMAL,
validate: {
min: 0,
max: 1
}
}
});
this.Article.belongsToMany(this.Label, { through: { model: this.ArticleLabel, unique: false } });
this.Label.belongsToMany(this.Article, { through: { model: this.ArticleLabel, unique: false } });
return this.sequelize.sync({ force: true })
.then(() => Promise.all([
this.Article.create({ title: 'Article' }),
this.Label.create({ text: 'Awesomeness' }),
this.Label.create({ text: 'Epicness' })
]))
.then(([article, label1, label2]) => Promise.all([
article,
label1,
label2,
article.addLabel(label1, {
through: { relevance: 1 }
}),
article.addLabel(label2, {
through: { relevance: .54 }
}),
article.addLabel(label2, {
through: { relevance: .99 }
})
]))
.then(([article, label1, label2]) => article.hasLabels([
label1[this.Label.primaryKeyAttribute],
label2[this.Label.primaryKeyAttribute]
]))
.then(result => expect(result).to.be.true);
});
});
describe('countAssociations', () => {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!