I have the following code:
#!/usr/bin/env node
'use strict';
var Sequelize = require('sequelize');
var sequelize = new Sequelize('sqlite:file.sqlite');
var User = sequelize.define('User', { email: Sequelize.STRING});
var Thing = sequelize.define('Thing', { name: Sequelize.STRING});
Thing.belongsTo(User);
sequelize.sync({force: true}).then(function () {
return User.create({email: 'asdf@example.org'});
}).then(function (user) {
return Thing.create({
name: 'A thing',
User: user
}, {
include: [User]
});
}).then(function (thing) {
return Thing.findOne({where: {id: thing.id}, include: [User]});
}).then(function (thing) {
console.log(JSON.stringify(thing));
});
I get the following output:
ohnobinki@gibby ~/public_html/turbocase1 $ ./sqltest.js
Executing (default): INSERT INTO `Users` (`id`,`email`,`updatedAt`,`createdAt`) VALUES (NULL,'asdf@example.org','2015-12-03 06:11:36.904 +00:00','2015-12-03 06:11:36.904 +00:00');
Executing (default): INSERT INTO `Users` (`id`,`email`,`createdAt`,`updatedAt`) VALUES (1,'asdf@example.org','2015-12-03 06:11:36.904 +00:00','2015-12-03 06:11:37.022 +00:00');
Unhandled rejection SequelizeUniqueConstraintError: Validation error
at Query.formatError (/home/ohnobinki/public_html/turbocase1/node_modules/sequelize/lib/dialects/sqlite/query.js:231:14)
at Statement.<anonymous> (/home/ohnobinki/public_html/turbocase1/node_modules/sequelize/lib/dialects/sqlite/query.js:47:29)
at Statement.replacement (/home/ohnobinki/public_html/turbocase1/node_modules/sqlite3/lib/trace.js:20:31)
It seems that specifying {include: [User]}
instructs Sequelize to create a new User
instance matching the contents of user
. That is not my goal. In fact, I find it hard to believe that such behaviour would ever be useful—I at least have no use for it. I want to be able to have a long-living User
record in the database and at arbitrary times create new Thing
s which refer to the User
. In my shown example, I wait for the User
to be created, but in actual code it would likely have been freshly loaded through User.findOne()
.
I have seen other questions and answers say that I have to explicitly specify the implicitly-created UserId
column in my Thing.create()
call. When Sequelize provides an API like Thing.belongsTo(User)
, I shouldn’t have to be aware of the fact that a Thing.UserId
field is created. So what is the clean API-respecting way of creating a new Thing
which refers to a particular User
without having to guess the name of the UserId
field? When I load a Thing
and specify {include: [User]}
, I access the loaded user through the thing.User
property. I don’t think I’m supposed to know about or try to access a thing.UserId
field. In my Thing.belongsTo(User)
call, I never specify UserId
, I just treat that like an implementation detail I shouldn’t care about. How can I continue to avoid caring about that implementation detail when creating a Thing
?
The Thing.create()
call that works but looks wrong to me:
Thing.create({
name: 'A thing',
UserId: user.id
});