Igor Brizack
Igor Brizack

Reputation: 25

Why my sequelize association doesn't work?

I've created two Models User and Gasto(means spent in portuguese), these two tables has an association like One User to Many Gasto, so I'm trying to implement the OnDelete 'CASCADE' to when I delete one User all Gasto from this User has to be deleted together, but my association is not working. Can somebody help me?

My Database Config:

import 'dotenv/config'
import { Options } from 'sequelize'

const config: Options = {
  username: process.env.DB_USER ?? 'root',
  password: process.env.DB_PASS ?? '123456',
  database: 'gastos_app_db',
  host: process.env.DB_HOST ?? 'localhost',
  port: Number(process.env.DB_PORT) ?? 3002,
  dialect: 'mysql',
  dialectOptions: {
    timezone: 'Z'
  },
  logging: false
}

module.exports = config

Migration from User, Gasto has the same example.

'use strict'

/** @type {import('sequelize-cli').Migration} */
module.exports = {
  async up (queryInterface, Sequelize) {
    await queryInterface.createTable('users', {
      id: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        allowNull: false,
        autoIncrement: true,
        onDelete: 'CASCADE'
      },
      username: {
        type: Sequelize.STRING,
        allowNull: false
      },
      email: {
        type: Sequelize.STRING,
        allowNull: false
      },
      role: {
        type: Sequelize.STRING,
        allowNull: false
      },
      password: {
        type: Sequelize.STRING,
        allowNull: false
      }
    })
  },

  async down (queryInterface, Sequelize) {
    await queryInterface.dropTable('users')
  }
}

My Instance of the Sequelize and configurations.

import { Sequelize } from 'sequelize'
import * as config from '../config/database'

export default new Sequelize(config)

My Model of user and the Association.

import { DataTypes } from 'sequelize'
import db from '.'
import { Gasto } from './Gasto'

export const User = db.define('User', {
  id: {
    type: DataTypes.INTEGER,
    autoIncrement: true,
    allowNull: false,
    primaryKey: true
  },
  username: {
    type: DataTypes.STRING,
    allowNull: false
  },
  email: {
    type: DataTypes.STRING,
    allowNull: false
  },
  password: {
    type: DataTypes.STRING,
    allowNull: false
  },
  role: {
    type: DataTypes.STRING,
    allowNull: false
  }
}, {
  timestamps: false,
  tableName: 'users',
  underscored: true
})

User.hasMany(Gasto, {
  foreignKey: 'userId',
  onDelete: 'CASCADE'
})

Gasto.hasOne(User, {
  foreignKey: 'id'
})

Gasto Model:

import { DataTypes } from 'sequelize'
import db from '.'

export const Gasto = db.define('Gasto', {
  id: {
    type: DataTypes.INTEGER,
    autoIncrement: true,
    allowNull: false,
    primaryKey: true
  },
  userId: {
    type: DataTypes.INTEGER,
    allowNull: false
  },
  type: {
    type: DataTypes.STRING,
    allowNull: false
  },
  value: {
    type: DataTypes.INTEGER,
    allowNull: false
  },
  gastoDate: {
    type: DataTypes.STRING,
    allowNull: false
  }
}, {
  timestamps: false,
  tableName: 'gastos',
  underscored: true
})


Gasto Migration

'use strict'

/** @type {import('sequelize-cli').Migration} */
module.exports = {
  async up (queryInterface, Sequelize) {
    await queryInterface.createTable('gastos', {
      id: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        allowNull: false,
        autoIncrement: true
      },
      user_id: {
        type: Sequelize.INTEGER,
        allowNull: false
      },
      type: {
        type: Sequelize.STRING,
        allowNull: false
      },
      value: {
        type: Sequelize.STRING,
        allowNull: false
      },
      gasto_date: {
        type: Sequelize.STRING,
        allowNull: false
      }
    })
  },

  async down (queryInterface, Sequelize) {
    await queryInterface.dropTable('gastos')
  }
}

I've already readed the all documentations, and checked some old projects, but I can't found the right way to fix this.

Upvotes: 0

Views: 109

Answers (1)

Andrew T
Andrew T

Reputation: 81

Your user_id field in your migration to create the gastos table must have a Foreign Key definition inside of it, along with the on update/on delete logic you desire (Cascade).

user_id: {
  type: Sequelize.INTEGER,
  allowNull: false,
  references: {
    model: 'users',
    key: 'id',
  },
  onUpdate: 'cascade',
  onDelete: 'cascade'
}

You can find an example of this in the sequelize query interface documentation.

Upvotes: 1

Related Questions