I have recently switched from "normal" sequelize to migrations with sequelize-cli. Using the cli worked fine so far. But I am unsure how to use the models that are generated. In particular it seems that the way I do it, I have issues with the associations. They are properly created in the database, but in the code I get errors like Upvote is not associated to Video
I have created the models with the cli and tried to import and use them.
This is a snippet of the video
model generated by the cli:
module.exports = (sequelize, DataTypes) => {
const Video = sequelize.define('Video', {
userid: DataTypes.STRING,
...
}, {});
Video.associate = function(models) {
Video.hasMany(models.Upvote, { foreignKey: 'videoid', sourceKey: 'id' });
};
return Video;
};
Here comes a snippet of the migration:
let videos = function (queryInterface, Sequelize) {
return queryInterface.createTable('Videos', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
userid: {
type: Sequelize.STRING,
references: {
model: 'Users',
key: 'id'
},
},
...
});
};
This is the way I import the models:
const Video = require('../models/video')(dbConnector.sequelize, Sequelize.DataTypes);
I find it a little weird that I need to pass sequelize
and DataTypes
, since this was not necessary when I built the models myself. Is this the right way of importing them?
There is no error when I import them, and I can query them like Videos.findAll()
but the associations don't work. And I am not sure how to make them work, do I need to call the Video.associate(models)
function myself? That seems weird, too.
I must be doing something wrong in the way I use those models, please let me know what to do differently.
Sequelize cli will generate an index.js
inside models
directory which will have the following code,
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) ===
'.js');
})
.forEach(file => {
const model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
In the first set of code, it will import all models whereas in the second set, it will associate all models based on the association configured inside associate
method of each and every model.
For Example, in your case, the association between Video
and Upvote
can be defined as,
models/Video.js
module.exports = (sequelize, DataTypes) => {
const Video = sequelize.define('Video', {
id: DataTypes.STRING,
...
}, {});
Video.associate = function(models) {
Video.hasMany(models.Upvote, {
foreignKey: 'videoId',
sourceKey: 'id'
});
};
return Video;
};
models/Upvote.js
module.exports = (sequelize, DataTypes) => {
const Upvote = sequelize.define('Upvote', {
id: DataTypes.STRING,
videoId: DataTypes.STRING
...
}, {});
Upvote.associate = function(models) {
Upvote.belongsTo(models.Video, {
foreignKey: 'videoId',
targetKey: 'id'
});
};
return Upvote;
};
Hope this helps!!!