Skip to content

Commit

Permalink
fix(model): create instance with many-to-many association with extra …
Browse files Browse the repository at this point in the history
…column (#10034) (#10050)
  • Loading branch information
tsasaki609 authored and sushantdhiman committed Oct 23, 2018
1 parent 9857f36 commit 5dc314b
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 2 deletions.
18 changes: 16 additions & 2 deletions lib/model.js
Expand Up @@ -3809,7 +3809,8 @@ class Model {
if (!this._options.include || !this._options.include.length) return this;

// Nested creation for HasOne/HasMany/BelongsToMany relations
return Promise.map(this._options.include.filter(include => !(include.association instanceof BelongsTo)), include => {
return Promise.map(this._options.include.filter(include => !(include.association instanceof BelongsTo ||
include.parent && include.parent.association instanceof BelongsToMany)), include => {
let instances = this.get(include.as);

if (!instances) return Promise.resolve();
Expand All @@ -3831,8 +3832,21 @@ class Model {
const values = {};
values[include.association.foreignKey] = this.get(this.constructor.primaryKeyAttribute, {raw: true});
values[include.association.otherKey] = instance.get(instance.constructor.primaryKeyAttribute, {raw: true});
// Include values defined in the scope of the association

// Include values defined in the association
Object.assign(values, include.association.through.scope);
if (instance[include.association.through.model.name]) {
for (const attr of Object.keys(include.association.through.model.rawAttributes)) {
if (include.association.through.model.rawAttributes[attr]._autoGenerated ||
attr === include.association.foreignKey ||
attr === include.association.otherKey ||
typeof instance[include.association.through.model.name][attr] === undefined) {
continue;
}
values[attr] = instance[include.association.through.model.name][attr];
}
}

return include.association.throughModel.create(values, includeOptions);
});
} else {
Expand Down
38 changes: 38 additions & 0 deletions test/integration/associations/belongs-to-many.test.js
Expand Up @@ -1786,6 +1786,44 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), () => {
return ctx.worker.addTask(ctx.task);
});
});

it('should be able to create an instance along with its many-to-many association which has an extra column in the junction table', function() {
const Foo = this.sequelize.define('foo', { name: Sequelize.STRING });
const Bar = this.sequelize.define('bar', { name: Sequelize.STRING });
const FooBar = this.sequelize.define('foobar', { baz: Sequelize.STRING });
Foo.belongsToMany(Bar, { through: FooBar });
Bar.belongsToMany(Foo, { through: FooBar });

return this.sequelize.sync({force: true}).then(() => {
return Foo.create({
name: 'foo...',
bars: [
{
name: 'bar...',
foobar: {
baz: 'baz...'
}
}
]
}, {
include: Bar
});
}).then(foo => {
expect(foo.name).to.equal('foo...');
expect(foo.bars).to.have.length(1);
expect(foo.bars[0].name).to.equal('bar...');
expect(foo.bars[0].foobar).to.not.equal(null);
expect(foo.bars[0].foobar.baz).to.equal('baz...');

return Foo.findOne({ include: Bar });
}).then(foo => {
expect(foo.name).to.equal('foo...');
expect(foo.bars).to.have.length(1);
expect(foo.bars[0].name).to.equal('bar...');
expect(foo.bars[0].foobar).to.not.equal(null);
expect(foo.bars[0].foobar.baz).to.equal('baz...');
});
});
});

describe('set', () => {
Expand Down

0 comments on commit 5dc314b

Please sign in to comment.