Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: make the include option of Model.create default to all provided associations #16922

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
16 changes: 15 additions & 1 deletion packages/core/src/model-internals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import NodeUtil from 'node:util';
import type { IndexOptions } from './dialects/abstract/query-interface.js';
import type { WhereAttributeHash } from './dialects/abstract/where-sql-builder-types.js';
import { EagerLoadingError } from './errors';
import type { Attributes, Model, Transactionable } from './model';
import type { Attributes, Model, ModelStatic, Transactionable } from './model';
import type { ModelDefinition } from './model-definition.js';
import type { Sequelize } from './sequelize';
import { isModelStatic } from './utils/model-utils.js';
Expand Down Expand Up @@ -273,3 +273,17 @@ Either add a primary key to this model, or use one of the following alternatives
);
}
}

export function getDefaultCreateInclude(model: ModelStatic, values: Object) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export function getDefaultCreateInclude(model: ModelStatic, values: Object) {
export function getDefaultCreateInclude(model: ModelStatic, values: UnknownRecord) {

const associations = [];
const associationNames = Object.keys(model.associations);
if (values) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

based on the typing, this condition is always true

for (const value of Object.keys(values)) {
if (associationNames.includes(value)) {
associations.push(value);
}
}
}

return associations;
}
2 changes: 2 additions & 0 deletions packages/core/src/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { BaseSqlExpression } from './expression-builders/base-sql-expression.js'
import {
_validateIncludedElements,
combineIncludes,
getDefaultCreateInclude,
getModelPkWhere,
setTransactionFromCls,
throwInvalidInclude,
Expand Down Expand Up @@ -1916,6 +1917,7 @@ ${associationOwner._getAssociationDebugList()}`);
*/
static async create(values, options) {
options = cloneDeep(options) ?? {};
options.include ??= getDefaultCreateInclude(this, values);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think belongs inside of save when isNewRecord is true, because calling build then save should work too


return await this.build(values, {
isNewRecord: true,
Expand Down
31 changes: 31 additions & 0 deletions packages/core/test/integration/model/create.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1593,6 +1593,37 @@ describe(Support.getTestDialectTeaser('Model'), () => {
});
});
});
it('should create associated objects without include option', async function () {
const Player = this.customSequelize.define('player', {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const Player = this.customSequelize.define('player', {
const Player = this.customSequelize.define('Player', {

name: {
type: DataTypes.STRING,
},
teamId: {
type: DataTypes.INTEGER,
},
});
const Team = this.customSequelize.define('team', {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const Team = this.customSequelize.define('team', {
const Team = this.customSequelize.define('Team', {

id: {
type: DataTypes.INTEGER,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
},
});
Player.team = Player.belongsTo(Team, {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Player.team = Player.belongsTo(Team, {
Player.belongsTo(Team, {

as: 'team',
foreignKey: 'teamId',
targetKey: 'id',
});
await this.customSequelize.sync({ force: true });
const createdPlayer = await Player.create({
name: 'Player 1',
team: { id: 1, name: 'My new team' },
});
expect(createdPlayer.team instanceof Team).to.be.ok;
expect(createdPlayer.teamId).to.equal(1);
});
});

it('should return autoIncrement primary key (create)', async function () {
Expand Down