From 3e5206023623e8f9f79830659e093d8f410149ca Mon Sep 17 00:00:00 2001 From: garretaserra Date: Sat, 10 Jun 2023 21:29:21 +0200 Subject: [PATCH 1/4] feat: Add information on extra attributes on join table in N:M relationships --- .../advanced-many-to-many.md | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/versioned_docs/version-6.x.x/advanced-association-concepts/advanced-many-to-many.md b/versioned_docs/version-6.x.x/advanced-association-concepts/advanced-many-to-many.md index f497b2e7..91b678a1 100644 --- a/versioned_docs/version-6.x.x/advanced-association-concepts/advanced-many-to-many.md +++ b/versioned_docs/version-6.x.x/advanced-association-concepts/advanced-many-to-many.md @@ -368,6 +368,44 @@ Person.belongsToMany(Person, { as: 'Children', through: 'PersonChildren' }) // This will create the table PersonChildren which stores the ids of the objects. ``` +## Associations with extra attributes on through table + +When creating an N:M association, for example, with User and Project through UserProjects you might want extra attributes in the join table like the "role" attribute . This relationship can be setup like this: + +```js +const User = sequelize.define('User', { + username: DataTypes.STRING, +}, { timestamps: false }); + +const Project = sequelize.define('Project', { + name: DataTypes.STRING +}, { timestamps: false }); + +const UserProjects = sequelize.define('UserProjects', { + role: DataTypes.STRING +}, { timestamps: false }); + +User.belongsToMany(Project, { through: UserProjects}) +Project.belongsToMany(User, { through: UserProjects}) +``` + +Creating multiple associations with the same extra attributes is possible by passing a single object on the through attribute: +```js +user1.setProjects([project1, project2, project3], { through: { role: 'admin' }}) +``` + +Setting different extra attributes per association can be done by passing an array of objects of the same length as the ammount of associations: +```js +user1.setProjects([project1, project2, project3], { + through: [ + { role: 'admin' }, + { role: 'manager' }, + { role: 'designer' }, + ] +}) +``` + + ## Specifying attributes from the through table By default, when eager loading a many-to-many relationship, Sequelize will return data in the following structure (based on the first example in this guide): From 51671233225e4a8a7adbd08c5710042e588561de Mon Sep 17 00:00:00 2001 From: garretaserra Date: Sun, 25 Jun 2023 17:45:32 +0200 Subject: [PATCH 2/4] feat: Move documentation from v6 to v7 --- .../advanced-many-to-many.md | 37 ++++++++++++++++++ .../advanced-many-to-many.md | 38 ------------------- 2 files changed, 37 insertions(+), 38 deletions(-) diff --git a/docs/advanced-association-concepts/advanced-many-to-many.md b/docs/advanced-association-concepts/advanced-many-to-many.md index 4ad22b1e..d38dc606 100644 --- a/docs/advanced-association-concepts/advanced-many-to-many.md +++ b/docs/advanced-association-concepts/advanced-many-to-many.md @@ -368,6 +368,43 @@ Person.belongsToMany(Person, { as: 'Children', through: 'PersonChildren' }) // This will create the table PersonChildren which stores the ids of the objects. ``` +## Associations with extra attributes on through table + +When creating an N:M association, for example, with User and Project through UserProjects you might want extra attributes in the join table like the "role" attribute . This relationship can be setup like this: + +```js +const User = sequelize.define('User', { + username: DataTypes.STRING, +}, { timestamps: false }); + +const Project = sequelize.define('Project', { + name: DataTypes.STRING +}, { timestamps: false }); + +const UserProjects = sequelize.define('UserProjects', { + role: DataTypes.STRING +}, { timestamps: false }); + +User.belongsToMany(Project, { through: UserProjects}) +Project.belongsToMany(User, { through: UserProjects}) +``` + +Creating multiple associations with the same extra attributes is possible by passing a single object on the through attribute: +```js +user1.setProjects([project1, project2, project3], { through: { role: 'admin' }}) +``` + +Setting different extra attributes per association can be done by passing an array of objects of the same length as the ammount of associations: +```js +user1.setProjects([project1, project2, project3], { + through: [ + { role: 'admin' }, + { role: 'manager' }, + { role: 'designer' }, + ] +}) +``` + ## Specifying attributes from the through table By default, when eager loading a many-to-many relationship, Sequelize will return data in the following structure (based on the first example in this guide): diff --git a/versioned_docs/version-6.x.x/advanced-association-concepts/advanced-many-to-many.md b/versioned_docs/version-6.x.x/advanced-association-concepts/advanced-many-to-many.md index 91b678a1..f497b2e7 100644 --- a/versioned_docs/version-6.x.x/advanced-association-concepts/advanced-many-to-many.md +++ b/versioned_docs/version-6.x.x/advanced-association-concepts/advanced-many-to-many.md @@ -368,44 +368,6 @@ Person.belongsToMany(Person, { as: 'Children', through: 'PersonChildren' }) // This will create the table PersonChildren which stores the ids of the objects. ``` -## Associations with extra attributes on through table - -When creating an N:M association, for example, with User and Project through UserProjects you might want extra attributes in the join table like the "role" attribute . This relationship can be setup like this: - -```js -const User = sequelize.define('User', { - username: DataTypes.STRING, -}, { timestamps: false }); - -const Project = sequelize.define('Project', { - name: DataTypes.STRING -}, { timestamps: false }); - -const UserProjects = sequelize.define('UserProjects', { - role: DataTypes.STRING -}, { timestamps: false }); - -User.belongsToMany(Project, { through: UserProjects}) -Project.belongsToMany(User, { through: UserProjects}) -``` - -Creating multiple associations with the same extra attributes is possible by passing a single object on the through attribute: -```js -user1.setProjects([project1, project2, project3], { through: { role: 'admin' }}) -``` - -Setting different extra attributes per association can be done by passing an array of objects of the same length as the ammount of associations: -```js -user1.setProjects([project1, project2, project3], { - through: [ - { role: 'admin' }, - { role: 'manager' }, - { role: 'designer' }, - ] -}) -``` - - ## Specifying attributes from the through table By default, when eager loading a many-to-many relationship, Sequelize will return data in the following structure (based on the first example in this guide): From 54d88d3141fc84706690aacc0cf1f52630111718 Mon Sep 17 00:00:00 2001 From: garretaserra Date: Mon, 26 Jun 2023 20:34:37 +0200 Subject: [PATCH 3/4] feat: Move extra attributes doc to rewritten v7 --- docs/associations/belongs-to-many.md | 37 ++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/docs/associations/belongs-to-many.md b/docs/associations/belongs-to-many.md index 4ba71ce8..670651da 100644 --- a/docs/associations/belongs-to-many.md +++ b/docs/associations/belongs-to-many.md @@ -477,4 +477,41 @@ const count = await post.countBooks(); // highlight-end ``` +## Associations with extra attributes on through table + +When creating an N:M association, for example, with User and Project through UserProjects you might want extra attributes in the join table like the "role" attribute . This relationship can be setup like this: + +```js +const User = sequelize.define('User', { + username: DataTypes.STRING, +}, { timestamps: false }); + +const Project = sequelize.define('Project', { + name: DataTypes.STRING +}, { timestamps: false }); + +const UserProjects = sequelize.define('UserProjects', { + role: DataTypes.STRING +}, { timestamps: false }); + +User.belongsToMany(Project, { through: UserProjects}) +Project.belongsToMany(User, { through: UserProjects}) +``` + +Creating multiple associations with the same extra attributes is possible by passing a single object on the through attribute: +```js +user1.setProjects([project1, project2, project3], { through: { role: 'admin' }}) +``` + +Setting (or adding) different extra attributes per association can be done by passing an array of objects of the same length as the ammount of associations: +```js +user1.setProjects([project1, project2, project3], { + through: [ + { role: 'admin' }, + { role: 'manager' }, + { role: 'designer' }, + ] +}) +``` + [^1]: The source model is the model that defines the association. From 1a533c3017fb1ce36cd8c8e8c5c314ee9a45df54 Mon Sep 17 00:00:00 2001 From: garretaserra Date: Sat, 22 Jul 2023 13:05:25 +0200 Subject: [PATCH 4/4] docs: Updated extra attributes example to typescript --- docs/associations/belongs-to-many.md | 90 ++++++++++++++++------------ 1 file changed, 53 insertions(+), 37 deletions(-) diff --git a/docs/associations/belongs-to-many.md b/docs/associations/belongs-to-many.md index 670651da..9d46720d 100644 --- a/docs/associations/belongs-to-many.md +++ b/docs/associations/belongs-to-many.md @@ -98,6 +98,59 @@ class Toot extends Model, InferCreationAttributes> { In TypeScript, you need to declare the typing of your foreign keys, but they will still be configured by Sequelize automatically. You can still, of course, use any [attribute decorator](../models/defining-models.mdx) to customize them. +### Associations with extra attributes on through table + +When creating an N:M association, for example, with User and Project through UserProjects you might want extra attributes on the junction table like the "role" attribute. +This relationship can be setup like this: + +```ts +class UserProject extends Model, InferCreationAttributes> { + @Attribute(DataTypes.STRING) + declare role: string; + + declare projectId: number; + declare userId: number; +} + +class Project extends Model, InferCreationAttributes> { + @Attribute(DataTypes.STRING) + declare name: string; + + declare UserProject?: NonAttribute; +} + +class User extends Model, InferCreationAttributes> { + @Attribute(DataTypes.STRING) + declare username: string; + + @BelongsToMany(() => Project, { + through: UserProject, + }) + declare projects?: NonAttribute; + + declare getProjects: BelongsToManyGetAssociationsMixin; + declare setProjects: BelongsToManySetAssociationsMixin; + declare addProjects: BelongsToManyAddAssociationsMixin; +} +``` + +Creating multiple associations with the same extra attributes is possible by passing a single object on the through attribute: +```ts +user1.setProjects([project1, project2, project3], { through: { role: 'admin' }}) +``` + +With the [set](#association-setter-setx) and [add](#association-adder-addx) mixins different extra attributes per association can be set by passing an array of objects of the same length as the ammount of associations: +```ts +user1.setProjects([project1, project2, project3], { + through: [ + { role: 'admin' }, + { role: 'manager' }, + { role: 'designer' }, + ] +}) +(await user1.getProducts()).map(x => x.UserProduct?.role) // [ 'admin', 'manager', 'designer' ] +``` + ## Inverse Association The `BelongsToMany` association automatically creates the inverse association on the target model, which is also a `BelongsToMany` association. @@ -477,41 +530,4 @@ const count = await post.countBooks(); // highlight-end ``` -## Associations with extra attributes on through table - -When creating an N:M association, for example, with User and Project through UserProjects you might want extra attributes in the join table like the "role" attribute . This relationship can be setup like this: - -```js -const User = sequelize.define('User', { - username: DataTypes.STRING, -}, { timestamps: false }); - -const Project = sequelize.define('Project', { - name: DataTypes.STRING -}, { timestamps: false }); - -const UserProjects = sequelize.define('UserProjects', { - role: DataTypes.STRING -}, { timestamps: false }); - -User.belongsToMany(Project, { through: UserProjects}) -Project.belongsToMany(User, { through: UserProjects}) -``` - -Creating multiple associations with the same extra attributes is possible by passing a single object on the through attribute: -```js -user1.setProjects([project1, project2, project3], { through: { role: 'admin' }}) -``` - -Setting (or adding) different extra attributes per association can be done by passing an array of objects of the same length as the ammount of associations: -```js -user1.setProjects([project1, project2, project3], { - through: [ - { role: 'admin' }, - { role: 'manager' }, - { role: 'designer' }, - ] -}) -``` - [^1]: The source model is the model that defines the association.