0

I want to make 3 tables Cliente, Obra and Engenheiro.

Associations: Cliente relates to Obra (1:n) and Engenheiro relates to Obra (m:n).

Cliente.js:

const db = require('./db');
const Obra = require('./Obra');

const Cliente = db.sequelize.define('clientes', {
    nome: {
        type: db.Sequelize.STRING
    },
    celular: {
        type: db.Sequelize.STRING
    },
    cpf: {
        type: db.Sequelize.STRING
    }
});

Cliente.hasMany(Obra);

//Cliente.sync({force: true})

module.exports = Cliente

Engenheiro.js:

const db = require('./db');
const Registro = require('./Registro');

const Engenheiro = db.sequelize.define('engenheiros', {
    nome: {
        type: db.Sequelize.STRING
    }
    crea: {
        type: db.Sequelize.STRING
    },
    salario: {
        type: db.Sequelize.FLOAT
    }
});

Engenheiro.hasMany(Obra);

//Engenheiro.sync({force: true})

module.exports = Engenheiro

Obra.js:

const db = require('./db')
const Cliente = require('./Cliente');
const Registro = require('./Registro');

const Obra = db.sequelize.define('obras', {
    bairro: {
        type: db.Sequelize.STRING
    },
    cidade: {
        type: db.Sequelize.STRING
    },
    estado: {
        type: db.Sequelize.STRING
    }
});

Obra.belongsTo(Cliente);
Obra.hasMany(Engenheiro);

//Obra.sync({force: true})

module.exports = Obra

Error message when i call "node something.js":
"something.hasMany called with something that's not a subclass of Sequelize.Model"

Update:
I tried what Anatoly said and it executed without any error, but I don't see a new column appearing and the sql code of the association didn't appear on the console, am i doing something wrong?
I create a new model "Registro.js" and moved the ".sync()" and the associations to a new file:

Association.js

const Cliente = require('./Cliente');
const Engenheiro = require('./Engenheiro');
const Obra = require('./Obra');
const Registro = require('./Registro');

Cliente.sync({force: true});
Engenheiro.sync({force: true});
Obra.sync({force: true});
Registro.sync({force: true});

Cliente.hasMany(Obra);
Obra.belongsTo(Cliente);
Obra.belongsToMany(Engenheiro, { through: Registro });
Engenheiro.belongsToMany(Obra, { through: Registro });

Registro.js(All models follow the same structure):

const db = require('./db');

const Registro = db.sequelize.define('registros', {});

module.exports = Registro

Console (the tables looks bigger because I added new columns):

Executing (default): DROP TABLE IF EXISTS `clientes`;
Executing (default): DROP TABLE IF EXISTS `engenheiros`;
Executing (default): DROP TABLE IF EXISTS `obras`;
Executing (default): DROP TABLE IF EXISTS `registros`;
Executing (default): CREATE TABLE IF NOT EXISTS `clientes` (`id` INTEGER NOT NULL auto_increment , `nome` VARCHAR(255), `end` VARCHAR(255), `fone` VARCHAR(255), `celular` VARCHAR(255), `cpf` VARCHAR(255), `cnpj` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;
Executing (default): CREATE TABLE IF NOT EXISTS `obras` (`id` INTEGER NOT NULL auto_increment , `end` VARCHAR(255), `bairro` VARCHAR(255), `cidade` VARCHAR(255), `estado` VARCHAR(255), `metragem` VARCHAR(255), `quartos` VARCHAR(255), `wc` VARCHAR(255), `infraestrutura` TINYINT(1), `garagem` TINYINT(1), `andar` VARCHAR(255), `edificio` VARCHAR(255), `situacao` VARCHAR(255), `dataInicio` DATETIME, `dataTermino` DATETIME, `observacao` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;
Executing (default): CREATE TABLE IF NOT EXISTS `engenheiros` (`id` INTEGER NOT NULL auto_increment , `nome` VARCHAR(255), `end` VARCHAR(255), `fone` VARCHAR(255), `celular` VARCHAR(255), `cpf` VARCHAR(255), `crea` VARCHAR(255), `salario` FLOAT, `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;
Executing (default): CREATE TABLE IF NOT EXISTS `registros` (`id` INTEGER NOT NULL auto_increment , `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;
Executing (default): SHOW INDEX FROM `clientes`
Executing (default): SHOW INDEX FROM `obras`
Executing (default): SHOW INDEX FROM `engenheiros`
Executing (default): SHOW INDEX FROM `registros`

Update2:
I managed to create the relationship columns by placing the associations before .sync() and changing force to alter but I still don't understand how associations work.
In the example below when I change the order of the .sync(alter: true) some table are not created neither updated, and the associations fail.

const Cliente = require('./Cliente');
const Obra = require('./Obra');
const Engenheiro = require('./Engenheiro');
const Registro = require('./Registro');

Cliente.hasMany(Obra);
Obra.belongsTo(Cliente);
Obra.belongsToMany(Engenheiro, {through: Registro});
Engenheiro.belongsToMany(Obra, {through: Registro});

Obra.sync({alter: true});
Engenheiro.sync({alter: true});
Cliente.sync({alter: true});
Registro.sync({alter: true});

Why the sync(force:true) causes the code to fail and why the order of the sync matter?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459

1 Answers1

0

First you need to do is move all association definitions outside of model files OR add them to associate method of models to call them all later after all models will be already registered, see my answer here for example.

Second, if you need M:N association you should create an additional table and define a model (let's say its name would be EngenheiroObra for instance) to link Engenheiro to Obra using belongsToMany method of a model.

Engenheiro.belongsToMany(Obra, { though: EngenheiroObra });
Obra.belongsToMany(Engenheiro, { though: EngenheiroObra });

Upd. You also need to remove all association definitions from model files if you already moved them outside. And you don't need old hasMany associations because you replaced them with belongsToMany ones.

Anatoly
  • 20,799
  • 3
  • 28
  • 42
  • Please add `Registro` model definition. – Anatoly Apr 12 '21 at 07:57
  • Also you should register all association BEFORE calling `sync` methods – Anatoly Apr 12 '21 at 07:57
  • In the sequelize's documentation says that i need to put the `hasMany` together with `belongsTo` to make one-to-many association. https://sequelize.org/master/manual/assocs.html#one-to-many-relationships – John Willian Apr 13 '21 at 00:27
  • For `Cliente` and `Obra` definitely, because you wish to link them as 1:n. But for `Engenheiro` and `Obra` you wish `m:n` that's why you need an additional table and model and use `belongsToMany` from both models to each other. – Anatoly Apr 13 '21 at 19:25