mickhansen / graphql-sequelize

GraphQL & Relay for MySQL & Postgres via Sequelize
MIT License
1.9k stars 172 forks source link

BelongsToMany associations #653

Closed sajadghawami closed 5 years ago

sajadghawami commented 5 years ago

Hey there,

i cant seem to get the associations working. I have a pretty straight forward belongsTo association. This is my sequelize model:

module.exports = function (sequelize, DataTypes) {
  const user = sequelize.define('user', {
    firstName: DataTypes.STRING,
    lastName: DataTypes.STRING,
    createdAt: {
      type: DataTypes.DATE,
    },
    updatedAt: {
      type: DataTypes.DATE,
    },
  });

  user.associate = function (model) {
    user.belongsToMany(model.group, {
      through: 'usersGroups',
      as: 'groups',
      foreignKey: 'userId',
    });
  return user;
};

This is the userQuery and userType:

const query = {
  user: {
    type: userType,
    args: {
      id: { type: GraphQLString },
    },
    resolve: resolver(user),
  },
  users: {
    type: new GraphQLList(userType),
    resolve: resolver(user),
  },
};

const type = new GraphQLObjectType({
  name: 'user',
  description: 'A user',
  fields: () => ({
    ...attributeFields(user),
    groups: {
      type: new GraphQLList(groupType),
      resolve: resolver(user.groups),
    },
  }),
});

I am getting the following error:

    {
      "message": "Cannot read property 'getTableName' of undefined",
      "locations": [
        {
          "line": 31,
          "column": 1
        }
      ],
      "path": [
        "users",
        0,
        "groups"
      ]
    },

Any clues would be appreciated! :)

Thanks!

mickhansen commented 5 years ago

Sounds like user.groups is undefined, start by verifying it exists.

sajadghawami commented 5 years ago

hmmm... I have a fully working rest-api and i am now trying to implement graphql.

Though i did not define the model for the pivot table since this isn't required for sequelize. Could this be the problem?

Would you mind opening the issue again? Maybe someone else has a clue

mickhansen commented 5 years ago

First you need to verify whether or not user.groups is defined, please put a console.log(user.groups) right before new GraphQLObjectType and paste the output.

sajadghawami commented 5 years ago

thanks for the reply!

gotcha! It is actually undefined- how do i access the association above?

i have honestly pretty much read each and every issue ever posted here and could not find the solution. I looked through the tests:

https://github.com/mickhansen/graphql-sequelize/blob/82ceb94521b5aec497a9cddce35240b885cc8b02/test/integration/resolver.test.js#L86

https://github.com/mickhansen/graphql-sequelize/blob/82ceb94521b5aec497a9cddce35240b885cc8b02/test/integration/resolver.test.js#L154

These are the line where the tests are basically the same as what i wrote... been trying to solve this for quite some time now...

The only difference seems to be the name of the pivot-table

mickhansen commented 5 years ago

You access it however you like, model[association] is not something built into sequelize, it's just a pattern used by some users where they save a reference to the association.

resolver takes either a model reference, an association reference or a function resolving to either.

They are also saved internally via model.associations: https://github.com/sequelize/sequelize/blob/master/lib/associations/mixin.js#L78

mickhansen commented 5 years ago

Do you have a piece of code that says user.groups = user.belongsToMany(....)?

sajadghawami commented 5 years ago

Actually i dont, so if i got you right, this part:

module.exports = function (sequelize, DataTypes) {
  const user = sequelize.define('user', {
    firstName: DataTypes.STRING,
    lastName: DataTypes.STRING,
    createdAt: {
      type: DataTypes.DATE,
    },
    updatedAt: {
      type: DataTypes.DATE,
    },
  });

  user.associate = function (model) {
    user.belongsToMany(model.group, {
      through: 'usersGroups',
      as: 'groups',
      foreignKey: 'userId',
    });
  return user;
};

Does not really give me access to user.groups? Any possibility to use my model with the resolver and get the groups? Or do i need to refactor it?

mickhansen commented 5 years ago

@sajadghawami As i just wrote, user.groups is a user pattern, if you don't follow the pattern of assigning the association like that, it won' exist.

Look at the code i referenced, you can access associations in other ways.

mickhansen commented 5 years ago

Something like user.getAssociationForAlias(model.group, 'groups') maybe, you'd have to experiment.

sajadghawami commented 5 years ago

damn, thanks dude, you just made my day - it worked :)