paulovitorjp
paulovitorjp

Reputation: 538

Helper methods and associations with include not working on sequelize

I can't call the helper methods that should have been generated by sequelize when using belongsTo/hasMany. And I cannot eager load a table. When trying to run the helper methods I get a message saying there is no such method, and when trying to use findAll with include passing the other table it says that the tables are not associated, please see details below:

models directory:

./models
--ticket.js
--category.js
--index.js

ticket.js

'use strict';

module.exports = function(sequelize, DataTypes) {
  var Ticket = sequelize.define('Ticket', {
    // category_id: DataTypes.INTEGER,
    subject: DataTypes.STRING,
    description: DataTypes.TEXT,
    requester_name: DataTypes.STRING,
    requester_email: DataTypes.STRING,
    owner_email: DataTypes.STRING,
    status: {
      type: DataTypes.ENUM,
      values: ['opened', 'in progress', 'closed']
    }
  }, {
    underscored: true,
    classMethods: {
      associate: function(models) {
        // associations can be defined here
        Ticket.belongsTo(models['Category']);
        Ticket.hasMany(models['Interaction']);
      }
    }
  });

  return Ticket;
};

category.js

'use strict';

module.exports = function(sequelize, DataTypes) {
  var Category = sequelize.define('Category', {
    name: DataTypes.STRING
  }, {
    underscored: true,
    classMethods: {
      associate: function(models) {
        // associations can be defined here
        Category.hasMany(models['Ticket']);
      }
    }
  });
  return Category;
};

index.js

'use strict';

var fs        = require('fs');
var path      = require('path');
var Sequelize = require('sequelize');
var basename  = path.basename(module.filename);
var env       = process.env.NODE_ENV || 'development';
var config    = require(__dirname + '/../config/config.json')[env];
var db        = {};

if (config.use_env_variable) {
  var sequelize = new Sequelize(process.env[config.use_env_variable]);
} else {
  var sequelize = new Sequelize(config.database, config.username, config.password, config);
}

fs
  .readdirSync(__dirname)
  .filter(function(file) {
    return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
  })
  .forEach(function(file) {
    var model = sequelize['import'](path.join(__dirname, file));
    db[model.name] = model;
  });

Object.keys(db).forEach(function(modelName) {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

Then I create constants for the models:

const models = require('../models'),
    Ticket = models['Ticket'],
    Category = models['Category'];

When trying to call Ticket.getCategory(), like below:

Ticket.findById(req.params.ticket_id).then((ticket) => {
        ticket.getCategory().then((category)=>{
            ticket['category'] = category;
            res.json(ticket);
        });
    });

I get:

Executing (default): SELECT `id`, `subject`, `description`, `requester_name`, `requester_email`, `owner_email`, `status`, `created_at`, `updated_at` FROM `Tickets` AS `Ticket` WHERE `Ticket`.`id` = '1';
Unhandled rejection TypeError: ticket.getCategory is not a function

If I try to use eager loading, like below:

Ticket.findAll({where:{id:req.params.ticket_id},include:[Category]}).then((ticket) => {
    res.json(ticket);
});

I get:

Unhandled rejection SequelizeEagerLoadingError: Category is not associated to Ticket!

What am I doing wrong?

Thanks in advance!

Upvotes: 0

Views: 3703

Answers (2)

Aren Hovsepyan
Aren Hovsepyan

Reputation: 2047

As you said you are using seqielize ^4.2.0, which is major update API has little changes.'

In version 4 you shouldn't add class methods through classMethods object, instead you should do this.

var Ticket = sequelize.define('Ticket', {
    // category_id: DataTypes.INTEGER,
    subject: DataTypes.STRING,
    description: DataTypes.TEXT,
    requester_name: DataTypes.STRING,
    requester_email: DataTypes.STRING,
    owner_email: DataTypes.STRING,
    status: {
      type: DataTypes.ENUM,
      values: ['opened', 'in progress', 'closed']
    }
  }, {
    underscored: true,
});

Ticket.associate = function(models) {
    // associations can be defined here
    Ticket.belongsTo(models['Category']);
    Ticket.hasMany(models['Interaction']);
};

You can read how to upgrade from sequelize 3 to 4 here

Upvotes: 1

yBrodsky
yBrodsky

Reputation: 5041

The problem is that your associations are not completely done. You need to specify a foreign key. For example:

module.exports = function(sequelize, DataTypes) {
  var Ticket = sequelize.define('Ticket', {
    //blablabla
  }, {
    underscored: true,
    classMethods: {
      associate: function(models) {
        // here specify which are your foreign keys
        // category_id is just to illustrate
        Ticket.belongsTo(models['Category'], {foreignKey: category_id});
        Ticket.hasMany(models['Interaction'], {foreignKey: something_id});
      }
    }
  });

  return Ticket;
};

This also needs to be done in the counterpart, Category and Interaction in this case. Then you will be able to use the sequelize magic

Upvotes: 1

Related Questions