I'm new to Sequelize.js and Databases in general, i haven't used migrations before, but i know that they can be used to make changes to the tables structure in a non-destructive way.
However i'm not sure where to declare column options (notNull, references, validate, ENUM values, etc...)
Should i declare such options in the the model file, or migration file? or both?
Wouldn't adding the options to both model and migration cause duplicate code?
(keep in mind that i'm talking about the initial migrations that create tables to the database, not the migrations that add columns and stuff...)
Any help would be appreciated!
I see three options you can take. The first two options might be edge cases but it helps to understand.
You want to prototype a project and you don't mind losing your data, then you could potentially do not care about migration files and synchronize your database according to your model with:
await sequelize.sync({ force: true });
It will execute on all your models:
DROP TABLE IF EXISTS "your_model" CASCADE;
CREATE TABLE IF NOT EXISTS "your_model" (...)
This command can be executed at the start of your application for example.
As you mentioned you don't want to add columns and stuff, it's probably a good option.
Now if you don't want to lose data, you could simply use the sync method without the force option:
await sequelize.sync({ });
It will only generate:
CREATE TABLE IF NOT EXISTS "your_model" (...)
Hence, your tables are created according to your models and you don't have to create migration files.
However, if you want to modify your model and it's the most frequent usecase, the new column will not be generated in the table dynamically that's why you need migration scripts.
You will have to define both migration file and your model. That's what the cli does. Here is an example:
# npx sequelize-cli init or create migrations and models folders
npx sequelize-cli model:generate --name User --attributes firstName:string,email:string
Now you will have two more files:
// migrations/<date>-create-user.js
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Users', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
firstName: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: (queryInterface, Sequelize) => {
// I usually remove this and create the table only if not exists
return queryInterface.dropTable('Users');
}
};
// models/users.js
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
firstName: DataTypes.STRING,
email: DataTypes.STRING
}, {});
User.associate = function(models) {
// associations can be defined here
};
return User;
};
You could refactor the code from the migration and the model, however it will be rather cumbersome because some migration files will only add one column, so merging all of them into the model might probably be less clear.
You should do it in both because as time goes by your models and inital migration will differ from each other. So I suppose you should determine a final structure in models and after that create an initial migration.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With