Reputation: 4853
I am confused on the intended workflow with Sequelize. I have found some documentation that refers to a workflow that uses sequelize-cli
, while others seem to create bespoke one-off javascript scripts that do the initialization. It seems the framework and tooling are largely flexible, but that flexibility results in a confusing and steep learning curve for beginners.
I want to create a simple 1:M model and have the db initialized with the corresponding schema. Simplified model concept:
Destination:
title:string
description:string
Views: (things to do at Destination
)
title:string
description:string
Associations: Destinations have many Views, Views have one Destination. Using the CLI we can do something like:
# Destinations
sequelize-cli --env $ENV \
model:create \
--name Destinations \
--attributes \
title:string,description:string
# Views
sequelize-cli --env $ENV \
model:create \
--name Views \
--attributes \
title:string,description:string
This results in a model and a migration being generated for both:
./models/destination.js
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Destinations extends Model {
static associate(models) {
}
}
Destinations.init({
title: DataTypes.STRING,
description: DataTypes.STRING,
}, {
sequelize,
modelName: 'Destinations',
});
return Destinations;
};
./models/views.js
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Views extends Model {
static associate(models) {
}
}
Views.init({
title: DataTypes.STRING,
description: DataTypes.STRING,
}, {
sequelize,
modelName: 'Views',
});
return Views;
};
And associated migrations:
./migrations/<number>-create-destinations.js
'use strict';
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('Destinations', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
title: {
type: Sequelize.STRING
},
description: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
async down(queryInterface, Sequelize) {
await queryInterface.dropTable('Destinations');
}
};
./migrations/<number>-create-views.js
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('Views', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
title: {
type: Sequelize.STRING
},
description: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
async down(queryInterface, Sequelize) {
await queryInterface.dropTable('Views');
}
};
And a small edit needs to be made to the model definitions to assign the associations:
In ./models/destination.js
static associate(models) {
Destinations.hasMany(models.Views)
}
In ./models/views.js
static associate(models) {
Views.hasOne(models.Destinations)
Views.belongsTo(models.Destinations)
}
And then you can use the CLI to create the db following your newly defined schema:
sequelize-cli --env development db:create
sequelize-cli --env development db:migrate
So this objectively seems like it would work, and seems to be the intended workflow from what I gather. And it sort of does work - except the associations are not accounted for in the created db schema. Presumably because the foreign keys and such are not defined in the migrations that the CLI generates. Further presumably because they are not defined in the --attributes
field of the CLI invocation.
So it seems like I need to manually add the associate()
function definition within each model definition and also patch the migration file after defining the associations? So then associate()
method is strictly for runtime and does not help define model schema relationships?
Am I missing something from my applied workflow? Am I using it incorrectly?
Upvotes: 0
Views: 27