Skip to content

Add an association (manyToMany) #139

@Looped8

Description

@Looped8

Hi,
I have 2 models, User and Department, with a third model (UserDepartment) being the join table of both in a many to many relation.

I am able to add a new Department to an User but Im not able to assign an already existing Department to an User.

UserModel:

/**
 * users model
 * @extends Model
 */
class UserModel extends Model {
  createdAt!: Date;
  updatedAt!: Date;

  /**
   * @override
   */
  static get tableName() {
    return 'users';
  }

  /**
   * @override
   */
  static get jsonSchema() {
    return {
      type: 'object',
      required: ['email','firstname','lastname','password',],
      search: ['email','firstname','lastname','cellphoneNumber','officeNumber','extensionNumber',],
      properties: {
        id: {
          type: 'integer'
        },
        email: {
          type: 'string'
        },
        firstname: {
          type: 'string'
        },
        lastname: {
          type: 'string'
        },
        cellphoneNumber: {
          type: 'string'
        },
        officeNumber: {
          type: 'string'
        },
        extensionNumber: {
          type: 'string'
        },
        password: {
          type: 'string'
        },
        isMaster: {
          type: 'boolean'
        },
        removed: {
          type: 'boolean'
        },
        createdAt: {
          type: 'date-time'
        },
        updatedAt: {
          type: 'date-time'
        },
        companyId: {
          type: 'integer'
        },
        usersGroupId: {
          type: 'integer'
        },
        avatarId: {
          type: 'integer'
        },
      }
    };
  }

  /**
   * @override
   */
  static get relationMappings() {
    return {
      company: {
        relation: Model.BelongsToOneRelation,
        modelClass: CompanyModel(),
        join: {
          from: 'users.companyId',
          to: 'companies.id'
        }
      },
      userGroup: {
        relation: Model.BelongsToOneRelation,
        modelClass: UserGroupModel(),
        join: {
          from: 'users.usersGroupId',
          to: 'users_groups.id'
        }
      },
      departments: {
        relation: Model.ManyToManyRelation,
        modelClass: DepartmentModel(),
        join: {
          from: 'users.id',
          through: {
            from: 'users_departments.userId',
            to: 'users_departments.departmentId',
            extra: ['canAssignAny'],
          },
          to: 'departments.id'
        }
      },
    };
  }
    
  $beforeInsert(): void {
    this.createdAt = this.updatedAt = new Date();
  }

  $beforeUpdate(): void {
    this.updatedAt = new Date();
  }

}`

DepartmentModel:

/**
 * departments model
 * @extends Model
 */
class DepartmentModel extends Model {
  createdAt!: Date;
  updatedAt!: Date;

  /**
   * @override
   */
  static get tableName() {
    return 'departments';
  }

  /**
   * @override
   */
  static get jsonSchema() {
    return {
      type: 'object',
      required: ['path',],
      search: ['path',],
      properties: {
        id: {
          type: 'integer'
        },
        path: {
          type: 'string'
        },
        removed: {
          type: 'boolean'
        },
        createdAt: {
          type: 'date-time',
          default: new Date(),
        },
        updatedAt: {
          type: 'date-time',
          default: new Date(),
        },
        companyId: {
          type: 'integer'
        },
      }
    };
  }

  /**
   * @override
   */
  static get relationMappings() {
    return {
      company: {
        relation: Model.BelongsToOneRelation,
        modelClass: CompanyModel(),
        join: {
          from: 'departments.companyId',
          to: 'companies.id'
        }
      },
      users: {
        relation: Model.ManyToManyRelation,
        modelClass: UserModel(),
        join: {
          from: 'departments.id',
          through: {
            from: 'users_departments.departmentId',
            to: 'users_departments.userId',
            extra: ['canAssignAny'],
          },
          to: 'users.id'
        }
      },
    };
  }
    
  $beforeInsert(): void {
    this.createdAt = this.updatedAt = new Date();
  }

  $beforeUpdate(): void {
    this.updatedAt = new Date();
  }

UserDepartmentModel:

/**
 * users_departments model
 * @extends Model
 */
class UserDepartmentModel extends Model {
  createdAt!: Date;
  updatedAt!: Date;

  /**
   * @override
   */
  static get tableName() {
    return 'users_departments';
  }

  /**
   * @override
   */
  static get jsonSchema() {
    return {
      type: 'object',
      required: ['userId','departmentId',],
      search: [],
      properties: {
        canAssignAny: {
          type: 'boolean'
        },
        createdAt: {
          type: 'date-time',
          default: new Date(),
        },
        updatedAt: {
          type: 'date-time',
          default: new Date(),
        },
        userId: {
          type: 'integer'
        },
        departmentId: {
          type: 'integer'
        },
      }
    };
  }

  /**
   * @override
   */
  static get relationMappings() {
    return {
      user: {
        relation: Model.BelongsToOneRelation,
        modelClass: UserModel(),
        join: {
          from: 'users_departments.userId',
          to: 'users.id'
        }
      },
      department: {
        relation: Model.BelongsToOneRelation,
        modelClass: DepartmentModel(),
        join: {
          from: 'users_departments.departmentId',
          to: 'departments.id',
        }
      },
    };
  }
    
  $beforeInsert(): void {
    throw new Error ('caca');
    this.createdAt = this.updatedAt = new Date();
  }

  $beforeUpdate(): void {
    this.updatedAt = new Date();
  }

This is what I do to create a new department on the fly and add it to an User:

const test1 = await app.service('users').patch(
    3, {
      departments: [
        {
          path: '/zazeaezeaze',
          companyId: 2,
          canAssignAny: true
        },
      ],
    });

It returns the User fields with an array departments containing the newly created Department

And this is what Im tryin to do to add an existing Department:

const test = await app.service('users').patch(
    3, {
      departments: [
        {
          id: 2,
          canAssignAny: true
        },
      ],
    });

Which fails to this:

type: 'NotFound',
  data: {
    message: 'model (id=2) is not a child of model (id=3). If you want to relate it, use the relate option. If you want to insert it with an id, use the insertMissing option',
    dataPath: [ 'departments', 0 ]
  },

Im certainly doing something wrong but cant figure out what.
Thanks.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions