36

Using Sequelize, I've created two models: User and Login.

Users can have more than one Login, but a login must have exactly one user, which means a Login cannot be saved without a User ID.

How do I .create a Login with a User association all in one swoop?

Current Code (Doesn't Work)

// Set up the models
var User = sequelize.define('User', {});
var Login = sequelize.define('Login', {});
Login.belongsTo(User, {
  onDelete: 'cascade',
  foreignKey: {
    field: 'userId',
    allowNull: false,
  }
});

// Create the instances
var user = User.create().then(function() {

  // THIS IS WHERE I WOULD LIKE TO SET THE ASSOCIATION
  var login = Login.create({
    userId: user.get('id')
  });

)};

The above results in SequelizeValidationError: notNull Violation: UserId cannot be null

slifty
  • 13,062
  • 13
  • 71
  • 109

8 Answers8

71

Assuming you have the right association between users and login, you can just create a user including a login:

User.create({
   name: "name",
   Login: {...}
},{
   include: Login
})

you can find more information here: https://sequelize.org/docs/v6/advanced-association-concepts/creating-with-associations/

xabitrigo
  • 1,341
  • 11
  • 24
Arwed Mett
  • 2,614
  • 1
  • 22
  • 35
19

First of all you need to setup the relations in both ways, like this:

// Set up the models
var User = sequelize.define('User', {});
var Login = sequelize.define('Login', {});

// Set the correct associations
User.hasMany(Login, {})
Login.belongsTo(User, {});

Then, you need to properly get the instances returned by the promises:

// Create the instances
User.create({}).then(function(newUser) {
    // now you can use newUser acessors to create the login
    return newUser.createLogin({});
).then(function(newLogin){
    // newLogin
}).catch(function(error){
    // error
});
Matheus Dal'Pizzol
  • 5,735
  • 3
  • 19
  • 29
  • 1
    Thanks Matheus. For folks looking at this from the future: the big mistake I was making is that .create returns a promise, not a user (.build returns a user). – slifty May 08 '15 at 17:55
  • 1
    This just helped my life! why does the documentation say `User.set()` instead of `User.create()`?? http://docs.sequelizejs.com/manual/tutorial/associations.html#associating-objects – jasonseminara Sep 17 '18 at 00:02
6

In your .then, the callback receives the model instance created by the previous call. You need to specify the argument inside the callback function.

var user = User.create().then(function(user) {

  // THIS IS WHERE I WOULD LIKE TO SET THE ASSOCIATION
  var login = Login.create({
    userId: user.get('id')
  });

  return login

}).then(function(login) {
    // all creation are complete. do something.
});

Also something important I would like to point out is your missing var statements! Those are important but not related to this question. See Declaring variables without var keyword

Community
  • 1
  • 1
Calvintwr
  • 8,308
  • 5
  • 28
  • 42
  • Thank you for the var callout! I blame the fact that I was slamming code together to try to understand how to use sequelize! (updated my example to reflect better practice). The big issue that caused confusion for me is that .create() returns a promise (while .build returns a user). – slifty May 08 '15 at 17:53
  • Technically both .create() and .build() returns a `promise`. `instanceof userByBuild // Promise` :) – Calvintwr May 10 '15 at 06:34
  • Darn! Well I have no excuse then! (and good to know for future) – slifty May 10 '15 at 13:51
  • @Calvintwr I have problem with this too! When I used `userId: user.id` it doesn't work and throw the error. After I changed it to `UserId: user.id` it works. Do you know about the issue? please help!!! – Quy Tang Mar 04 '17 at 08:23
  • it's probably because "UserId" is the field name of your User model. If you don't define the id field of your model, it will just use the name the model and add "Id" behind – Calvintwr Mar 04 '17 at 11:52
5

An Update to @Arwed Mett's answer

//Create Association Alias or just setting association alias by using 'as' keyword will also work
Login.User = Login.belongsTo(User);

User.create({
 name: "name",
  Login: {...}
}, {
  include: [{
    association: Login.User
  }]
});

Refrence link - http://docs.sequelizejs.com/manual/tutorial/associations.html#creating-with-associations

Kshateesh
  • 571
  • 1
  • 8
  • 21
2

For those like me who were trying to create an instance of a model including another instance, like:

var login1 = await Login.create(...);
var user1 = await User.create({
    Login: login1
}, {
    include: Login
});

You can't because this method is used to embed an instance (Login) which is not already existing and that will be created at the parent instance (User) creation level.

So, if you want to embed an already existing Login in the newly created User, do instead:

var login1 = await Login.create(...);
var user1 = await User.create({
    loginId: login1.get('id')
}, {});
  • bear in mind that, depending on how you have everything set up, you might have to capitalize `loginId` (as in: `LoginId: login1.get('id')`) – jaume Dec 06 '21 at 12:02
1

You have association between User an Login with constraint allowNull at false. You must create Login before User or set allowNull at true in model and the table to DB (LoginId Null constraint)

var User = sequelize.define('User', {});
var Login = sequelize.define('Login', {});
Login.belongsTo(User, {
  onDelete: 'cascade',
  foreignKey: {
    field: 'userId',
    allowNull: false,
  }
});

Solution

Login.create({
   username: "username",
   User: {...}
},{
   include: User
})
Achille Skineur
  • 111
  • 1
  • 3
0

I have the same issue recently! I have a typo mistake with the foreignKey config. Use field instead of name caused the issue.

The change below will fix it.

{
    foreignKey: {
       name: 'userId',
       allowNull: false,
    }
}
Quy Tang
  • 3,929
  • 1
  • 31
  • 45
0

As an extra you could also nest your creation to be even more effective and concise.

  // Set up the models
    var User = sequelize.define('User', {});
    var Login = sequelize.define('Login', {});
        ...


    User.create({
       name: "name",
       Login:
            {
            users: {..i.e several users if a user belongs to another user..}
            }
        },{
       include:{
      model: Login,
      include: User //nested model.Create
         }
    })

as seen here: https://github.com/sequelize/sequelize/issues/7252

iwaduarte
  • 1,600
  • 17
  • 23