Skip to content

defaultScope mutates after applying .scope(['defaultScope', 'otherScope']) #10696

@robbyphillips

Description

@robbyphillips

What are you doing?

With the code below, the default scope of the model seems to be overridden after doing Model.scope(['defaultScope', 'withBar']), leading to unexpected results.

const config = require('./config/config.json')
const Sequelize = require('sequelize')
const sequelize = new Sequelize(config['development'])

  const User = sequelize.define('User', {
    name: Sequelize.STRING,
    foo: Sequelize.BOOLEAN,
    bar: Sequelize.BOOLEAN,
    baz: Sequelize.BOOLEAN
  }, {});

  User.addScope('defaultScope', {
    where: { foo: true }
  }, { override: true })

  User.addScope('withBar', {
    where: { bar: true }
  })

  User.addScope('noBaz', {
    where: { baz: false }
  })

const users = [
  {
    name: 'Alice',
    foo: true,
    bar: true,
    baz: true
  },
  {
    name: 'Bob',
    foo: true,
    bar: true,
    baz: false,
  },
  {
    name: 'Charlie',
    foo: true,
    bar: false,
    baz: false,
  },
  {
    name: 'Danika',
    foo: false,
    bar: false,
    baz: false
  }
]

async function doStuff() {
  await sequelize.sync({force: true})
  await User.bulkCreate(users)

  const defaultscope = await User
    .findAll()
    .then(result => result.map(u => u.name))

  const withBar = await User
    .scope('withBar')
    .findAll()
    .then(result => result.map(u => u.name))

  const withBarAndDefault = await User
    .scope(['defaultScope', 'withBar'])
    .findAll()
    .then(result => result.map(u => u.name))

  const defaultscope2 = await User
    .findAll()
    .then(result => result.map(u => u.name))

  const noBaz = await User
    .scope('noBaz')
    .findAll()
    .then(result => result.map(u => u.name))

  const unscoped = await User
    .unscoped()
    .findAll()
    .then(result => result.map(u => u.name))

  const defaultscope3 = await User
    .findAll()
    .then(result => result.map(u => u.name))

  console.log('defaultscope: ', defaultscope)
  console.log('withBar: ', withBar)
  console.log('withBarAndDefault: ', withBarAndDefault)
  console.log('defaultscope2: ', defaultscope2)
  console.log('noBaz: ', noBaz)
  console.log('unscoped: ', unscoped)
  console.log('defaultscope3: ', defaultscope3)

  process.exit(0)
}

doStuff()

What do you expect to happen?

According to the docs .scope() should return a new model with the scope applied, so multiple invocations of User.scope().findAll() should have no bearing on each other.

Expected results:

defaultscope:  [ 'Alice', 'Bob', 'Charlie' ]
withBar:  [ 'Alice', 'Bob' ]
withBarAndDefault:  [ 'Alice', 'Bob' ]
defaultscope2:  [ 'Alice', 'Bob', 'Charlie' ]
noBaz:  [ 'Bob', 'Charlie', 'Danika' ]
unscoped:  [ 'Alice', 'Bob', 'Charlie', 'Danika' ]
defaultscope3:  [ 'Alice', 'Bob', 'Charlie' ]

What is actually happening?

Instead, later invocations of User.findAll() were affected.

Actual results:

// correct
defaultscope:  [ 'Alice', 'Bob', 'Charlie' ] 

// correct
withBar:  [ 'Alice', 'Bob' ]

// correct
withBarAndDefault:  [ 'Alice', 'Bob' ] 

// should include 'Charlie'
defaultscope2:  [ 'Alice', 'Bob' ]

 // correct
noBaz:  [ 'Bob', 'Charlie', 'Danika' ]

// correct
unscoped:  [ 'Alice', 'Bob', 'Charlie', 'Danika' ]

// should include 'Charlie'
defaultscope3:  [ 'Alice', 'Bob' ] 

Dialect: mysql
Dialect version: XXX (where do I find this?)
Database version: mysql Ver 15.1 Distrib 10.3.13-MariaDB, for Linux (x86_64) using readline 5.1
Sequelize version: 5.2.11
Tested with latest release: Yes, 5.2.11 (updated today)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions