transistor transistor - 4 years ago 330
Node.js Question

How to create foreign keys with sequelizejs in a feathersjs project

I am using featherjs v2.0.3 with sequelize v3.29.0 and I just created three models, the third having a relationship to the other two.

Tables

I used the feathers-cli to generate services for each and then edit the model file of each.

So far, so good, the tables are created (using PostgreSQL), indexes are created, feathersjs takes care of the CRUD nicely, but not foreign keys yet.

So, when I try to tell feathersjs the relationship between the models, I get in trouble.

When I add

role_permission.belongsTo(permissions)
to the
role_permission
model, I get this error:
ReferenceError: permissions is not defined


As I've seen in the Sequelize documentation, the models are defined in the same "document", hence I suspect the problem is somewhere there, but I don't understand what need to be done.

Feathersjs project structure

Finally, here's the relevant parts of the model definitions of
permission
and
role_permission
:

// permission-model.js - A sequelize model

module.exports = function(sequelize) {
const permission = sequelize.define('permissions', {
permission_id: {
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV1,
primaryKey: true,
allowNull: false
}...
}, ...);

permission.sync();

return permission;
};





// role_permission-model.js - A sequelize model

module.exports = function(sequelize) {
const role_permission = sequelize.define('role_permissions', {
permission_id: {
type: Sequelize.UUID,
allowNull: false
}...
}, ...);

role_permission.belongsTo(permissions) //<-- undefined?

role_permission.sync();

return role_permission;
};


Do you have any pointers to help me solve this?
Thanks!

Answer Source

You need to import the permissions model. But it may or may not be defined yet.

Here's a method I discovered from @mrpatiwi on github to ensure every model is loaded before the associations are set up.

First, when you need to define a relationship add a classMethod called associate that accepts all the models and sets up the relationships.

module.exports = function(sequelize) {
  const role_permission = sequelize.define('role_permisson', {
    ...
  }, {
    classMethods: {
      associate(models) {
        role_permission.belongsTo(models.permission);
      },
    },
  });

  // Don't add role_premission.sync() here

  return role_permission;
};

Then, in src/services/index.js at the end of the module.exports function, add:

// Setup relationships
const models = sequelize.models;
Object.keys(models)
  .map(name => models[name])
  .filter(model => model.associate)
  .forEach(model => model.associate(models));

sequalize.sync();
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download