This is my User model
'use strict';
var bcrypt = require('bcrypt');
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define('User', {
email: {
type: DataTypes.STRING,
validate: {
isEmail: true,
notEmpty: true,
notNull: false
},
unique: true
},
password: DataTypes.STRING,
name: DataTypes.STRING,
username: {
type: DataTypes.STRING,
unique: true
},
admin: DataTypes.BOOLEAN,
googleId: DataTypes.BOOLEAN
}, {
classMethods: {
associate: function(models) {
User.hasMany(models.Award);
User.hasMany(models.Media);
User.hasMany(models.Comment);
User.hasMany(models.Like);
User.hasMany(models.CheckIn);
}
}
});
return User;
};
and this is my Media model:
'use strict';
module.exports = function(sequelize, DataTypes) {
var Media = sequelize.define('Media', {
type: DataTypes.ENUM('photo', 'video'),
description: DataTypes.STRING,
url: DataTypes.STRING,
gps: DataTypes.GEOMETRY('POINT')
}, {
classMethods: {
associate: function(models) {
//Media.belongsTo(models.Event);
//Media.belongsTo(models.User);
Media.hasMany(models.Comment);
Media.hasMany(models.Like);
}
}
});
return Media;
};
And I'm getting this error:
Unhandled rejection Error: Cyclic dependency found. Users is dependent of itself.
Dependency chain: Awards -> Users -> Media => Users
Previously I had a cyclic dependency and it's now removed but sequelize still throws this error. Why is this happening?
If I remove the User.hasMany(models.Media) association the error will disappear. But why is it still happening when the Media model has no reference to the User model?
A cyclic dependency is an indication of a design or modeling problem in your software. Although you can construct your object graph by using property injection, you will ignore the root cause and add another problem: property injection causes Temporal Coupling. Instead, the solution is to look at the design closely.
Sequelize can add a foreign key constraint to the desired SQL table by using one of the following association methods: hasOne() belongsTo()
Constraints are the rules that we define on the level of SQL. For example, if one attribute is supposed to be unique then this will be handled on the level of SQL. If a constraint check fails then Sequelize will forward the error message sent by the database.
To create an attribute with a foreign key relationship, use the "references" and "referencesKey" fields: For example, the following would create a users table, and a user_emails table which references the users table. queryInterface. createTable('users', { id: { type: Sequelize.
Settings constraints: false
will work, but will not create the foreign key in your DB.
If all your db access is done from sequelize, that can be an acceptable solution. But if you access your DB in several ways, that becomes complicated to handle. E.g: Hasura does not create relationships between models.
The real issue is that sequelize is not smart enough to create the table in 2 steps. Other ORMs handle that by first creating the tableA without the foreign key, create the tableB with foreignKey to tableA, and alter TableA to create foreign key to tableB.
So the solution is to add constraints: false
to your User.hasMany(models.Media)
then create then run foreign key constrain.
const addMediaUserForeignKey = queryInterface.addConstraint(
'Media', {
type: 'foreign key',
onUpdate: 'CASCADE',
onDelete: 'CASCADE',
references: {
table: 'User',
field: 'id',
},
fields: [ 'userId' ]
}
).catch((e) => {})
Consider using hasMany as follows:
User.hasMany(models.Award, {as: 'ifYouWantAlias', constraints: false, allowNull:true, defaultValue:null});
note that you don't need the following part but it makes it clearer in my opinion.
allowNull:true, defaultValue:null
It is explained well in here: http://docs.sequelizejs.com/en/latest/api/associations/
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