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 Things 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
});