3

I have a seemingly common problem with sequelize. For context I am trying to assign a default role to each user that is created. Essentially each user's role should be set to default user when they are first registered.

I would like to be able to simply define this default value in my Models file as you would with normal fields but, I can't seem to find the correct syntax.

This is what my User model currently looks like:

'use strict';

import { Sequelize } from 'sequelize';

export default (sequelize: Sequelize) => {
  const Users = sequelize.define(
    'Users',
    {
      email: {
        type: Sequelize.STRING,
        allowNull: false
      },
      some_foreign_id: {
        type: Sequelize.STRING,
        allowNull: false
      }
    },
    {}
  );
  Users.associate = models => {
    // associations can be defined here
    Users.belongsTo(models.Roles, { as: 'Role' });
  };
  return Users;
};

Currently I am just making a query to find the role with the name default role and adding it to my user as it is created. However, I feel that query is unnecessary.

Based on the google autofill suggestions it seems like a lot of people have this problem without any clear solution.

[EDIT]

My role model (heh) currently looks like this:


import { Sequelize } from 'sequelize';

export default (sequelize: Sequelize) => {
  const Roles = sequelize.define(
    'Roles',
    {
      name: {
        type: Sequelize.STRING,
        allowNull: false
      }
    },
    {}
  );
  Roles.associate = models => {
    // associations can be defined here
    // SO note: This association is for my permissions. Should have nothing to do with my User association. 
    Roles.belongsToMany(models.Permissions, { through: 'RolePermission' });
  };
  return Roles;
};
Irfandy Jip
  • 1,308
  • 1
  • 18
  • 36
Michael Sorensen
  • 1,850
  • 12
  • 20
  • What does your `Role` model look like? Specifically any associations set to the `User` model – Rastalamm Jul 12 '19 at 18:31
  • @Rastalamm I've updated the OP with my `role` model. Currently there are no associations defined in that model as the one to many relationship is defined in the `user`'s model. If you have any insight I would definitely appreciate it! Does not necessarily have to be a complete answer haha – Michael Sorensen Jul 12 '19 at 18:38
  • It's been a month since you posted this, do you find any solution? I know a few _"work around"_ however it would be nice to know about this as well, been looking for it for a while. – Irfandy Jip Sep 04 '19 at 08:36
  • I did not and ended up using TypeORM instead of sequelize. However, it does look like the answer you posted is valid provided the screenshots so I'm going to mark that as the answer. Thank you for your help! – Michael Sorensen Sep 04 '19 at 16:37

3 Answers3

5

Old Answer, see updated below.

Hm.. I actually have the same problem right now, and I don't know wheter this is a good solution or not. But my models currently a bit the same with yours..

Here is my user model

// importing sequelize and stuff..

User.init({
  id: {
    type: INTEGER,
    primaryKey: true,
    autoIncrement: true
  },
  name: {
    type: STRING,
    allowNull: false
  },
  email: {
    type: STRING,
    allowNull: false,
    unique: true,
    validation: {
      isEmail: {
        msg: 'Not a valid email address'
      }
    } 
  },
  password: {
    type: STRING,
    allowNull: false
  },
  RoleId: {
    type: INTEGER,
    allowNull: false,
    defaultValue: 2
  }
}, {/* stuff */})

Notice the defaultValue property in RoleId.
And now it is my time to show you my role model (jokes unintended)

Role.init({
  id: {
    type: INTEGER,
    primaryKey: true,
    autoIncrement: true
  },
  name: {
    type: STRING,
    allowNull: false
  },
  level: {
    type: INTEGER,
    allowNull: false
  }
}, {/* stuff */})

And in my case, when I do POST /login in my user controller

// POST /users
  create(req, res) {
    const { name, email, password } = req.body
    return User.create({ name, email, password })
      .then(createdUser => res.json(createdUser))
      .catch(err => res.status(503).json({ msg: err }))
  }

Here is the result: Sequelize Result

Bewarned, I was just trying stuff and had no idea if this results are intended in sequelize. It also has been a while since I used Sequelize and notice that they had changed the naming of foreign key. As far as I remember it used to be camelCase, now it's PascalCase. Maybe others can help explaining those. My sequelize version is 5.15.0 at the time I wrote this.

Thank you :)

Whoops - Updated in just a few minutes..

Lucky me, I found this issue on GitHub as How to require a foreign key to be not null #2837 .

TL;DR

When associating between models you can use this..

User.belongsTo(Role, {
  foreignKey: {
    /* use this like `sequelize.define(...)` */
    allowNull: false,
    defaultValue: 2
  }
})
Irfandy Jip
  • 1,308
  • 1
  • 18
  • 36
0

When you query for User, just do an include

User.find({
  where: {
    id: 1
  },
  include: [{
    model: Role,
    as: 'Role'
  }]
}).then(foundUserWithRole => {
// do something here
}).catch(err => {});

This will return the role attached to the User every time you query for the user. Therefore you don't need to make a separate query for role.

Hackbyrd
  • 436
  • 5
  • 12
  • aye that is good for finding a `user` with a `role`. Maybe my post wasn't clear but, I'm trying to set a default `role` when _creating_ a user. If there is anything I can do to clarify my problem please let me know! – Michael Sorensen Jul 12 '19 at 18:40
0

Your User table is going to get a roleId column in it from the associate function. I believe you can just define that property in the User model and give it a default value property.

boc4life
  • 941
  • 5
  • 10