defaultScope mutates after applying .scope(['defaultScope', 'otherScope'])
See original GitHub issueWhat 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)
Issue Analytics
- State:
- Created 4 years ago
- Reactions:2
- Comments:15 (10 by maintainers)
Top Results From Across the Web
Scopes - Sequelize
The default scope is always applied. This means, that with the model definition above, Project.findAll() will create the following query:.
Read more >Scope transition mode - Documentation for BMC Discovery 22.1
All existing discovered devices are considered to be in the default scope. When you scan an endpoint, all scanned devices appear in the ......
Read more >about Scopes - PowerShell | Microsoft Learn
The default scope for scripts is the script scope. The default scope for functions and aliases is the local scope, even if they...
Read more >Sequelize attributes on include are overwriting defaultScope
findAll({ include: [{ model: Bar, // defaultScope does its work }], }) /* { . ... that defaultScope applies when no other scope...
Read more >Scope | SAP Help Portal
After selecting another scope and loading the Solution Documentation again, the selected scope is displayed. The default scope Show All is always available...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Just a quick note to point out that both Utils.cloneDeep and Lodash’s
_.cloneDeep
raise JavaScript heap out of memory errors when running the tests. My guess is there are some instances where the scopes can contain complex objects that should not be cloned. Avoided this problem by calling Lodash’s_.cloneDeepWith
specifying a function that results in cloning only plain objects.After digging a bit more into the code I should make clear that the
._scope
property isn’t exactly the defaultScope. As far as I understand that class, it contains the scope to apply in the next query, which should reference the defaultScope (if we defined one) under normal circumstances. If you want to make sure you are checking the defaultScope, it’s usually better to check.options.defaultScope
. In the provided example, both attributes work the same. You can also check other scopes through.options.scopes[<scope_name>]
(the defaultScope is not included inside that object).You are right, @WaylonOKC, that problem is still happening and though its cause is probably located in the same functions, looks unrelated to the scope overwriting. I’d say it’s happening again because of
Model._mergeFunction
. If we look around line 804:It’s clearly mixing the attributes objects by merging its inner arrays, which is the problem you are having (non-array properties are actually overwritten as you expect). Maybe it’s a bug, though it looks like a very explicit block of code to me. Probable better to wait for a core developer to shed some light onto this.