Home > front end >  Sequelize and defaultScope with Models associated
Sequelize and defaultScope with Models associated

Time:12-20

I am using Sequelize with Express, and Node js and I am trying to define defaultScope for Models. Card and Tag have a Many To Many association. Here are Models definitions and addScope

// Models Associations

// ONE TO MANY
List.hasMany(Card, {
  as: "cards",
});
Card.belongsTo(List, {
  as: "list",
});

// MANY TO MANY
Card.belongsToMany(Tag, {
  as: "tags",
  through: "card_has_tag",
  updatedAt: false,
});
Tag.belongsToMany(Card, {
  as: "cards",
  through: "card_has_tag",
  updatedAt: false,
});

// SCOPES
Card.addScope("defaultScope", {
  include: {
    association: "tags",
  },
});

List.addScope("defaultScope", {
  include: {
    association: "cards",
    include: "tags",
  },
});

// What I would like to implement
// If I comment lines below => List and Card queries are working
Tag.addScope("defaultScope", {
  include: {
    association: "cards",
  },
});

I would like to print by default all related infos with associated relations.

I want to get this info when I execute a sequelize query for each model.

  1. LISTS with associated :
  • cards
  • tags
  1. CARDS with associated:
  • tags
  1. TAGS with associated :
  • cards

I manage to get 1 & 2, but when I add Tag.addScopenothing is working anymore.

When I change defaultScope by another string by defining a scope all (for example) , and when I use model.scope("all").findAll(), this is working, but it is not what I would like to do becaue I want to use defaultScope to have a default behavior so I don't have to specify scope in queries command like (findAll...)

Is there a way I can do that ?

CodePudding user response:

The way you are trying to set it up results in an endless recursion, you simply can't have it like that.

If you set it up like that and query Card it will include Tag which will include Card which will include Tag and so on until you get Maximum call stack size exceeded.

There is a workaround you can use, which is to add another scope which includes nothing, then specify that scope for the model in the defaultScope.

Tag.addScope("noInclude", {});
Card.addScope("noInclude", {});

Tag.addScope("defaultScope", {
  include: [
    {
      model: Card.scope("noInclude"),
      as: "cards"
    }
  ]  
});

Card.addScope("defaultScope", {
  include: [
    {
      model: Tag.scope("noInclude"),
      as: "cards"
    }
  ]
});

This should give you the desired behaviour.

  • Related