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

Add an association (manyToMany) #139

Open
Looped8 opened this issue Dec 30, 2020 · 2 comments
Open

Add an association (manyToMany) #139

Looped8 opened this issue Dec 30, 2020 · 2 comments

Comments

@Looped8
Copy link

Looped8 commented Dec 30, 2020

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.

@zanzara
Copy link

zanzara commented Jan 25, 2022

I don't know, but it seems to me, that this repo is kinda dead.
I have also issues with manytoMany Asso. (posted it in discussion).
There are really lacking some "real-world" full-examples of best-practice done with feathers/Objection and relations.

Or is there another, better place to ask for? (forum?)

@dekelev
Copy link
Member

dekelev commented Jan 25, 2022

You can check the tests for more examples. Also, a lot of the info is in Objection website, so you search examples there as well.

I'm not using Feathers for almost a year now, which makes it difficult to continue and working on this project, hence it will progress with PR for the most part in order to add new features.

The project has an extensive test coverage and is used in production within many companies, so it is considers to be very stable.

@dekelev dekelev closed this as completed Jan 25, 2022
@dekelev dekelev reopened this Jan 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants