Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
public
/
sequelize
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
不要怂,就是干,撸起袖子干!
Commit 29c9be37
authored
Oct 19, 2019
by
Simon Schick
Committed by
Sushant
Oct 19, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix(model): make .changed() deep aware (#10851)
1 parent
481bddd6
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
51 additions
and
36 deletions
lib/model.js
test/unit/instance/changed.test.js
lib/model.js
View file @
29c9be3
...
@@ -104,7 +104,7 @@ class Model {
...
@@ -104,7 +104,7 @@ class Model {
this
.
dataValues
=
{};
this
.
dataValues
=
{};
this
.
_previousDataValues
=
{};
this
.
_previousDataValues
=
{};
this
.
_changed
=
{}
;
this
.
_changed
=
new
Set
()
;
this
.
_modelOptions
=
this
.
constructor
.
options
;
this
.
_modelOptions
=
this
.
constructor
.
options
;
this
.
_options
=
options
||
{};
this
.
_options
=
options
||
{};
...
@@ -160,12 +160,10 @@ class Model {
...
@@ -160,12 +160,10 @@ class Model {
delete
defaults
[
this
.
constructor
.
_timestampAttributes
.
deletedAt
];
delete
defaults
[
this
.
constructor
.
_timestampAttributes
.
deletedAt
];
}
}
if
(
Object
.
keys
(
defaults
).
length
)
{
for
(
key
in
defaults
)
{
for
(
key
in
defaults
)
{
if
(
values
[
key
]
===
undefined
)
{
if
(
values
[
key
]
===
undefined
)
{
this
.
set
(
key
,
Utils
.
toDefaultValue
(
defaults
[
key
],
this
.
sequelize
.
options
.
dialect
),
{
raw
:
true
});
this
.
set
(
key
,
Utils
.
toDefaultValue
(
defaults
[
key
],
this
.
sequelize
.
options
.
dialect
),
{
raw
:
true
});
delete
values
[
key
];
delete
values
[
key
];
}
}
}
}
}
}
}
...
@@ -2450,8 +2448,9 @@ class Model {
...
@@ -2450,8 +2448,9 @@ class Model {
const
hasPrimary
=
this
.
primaryKeyField
in
values
||
this
.
primaryKeyAttribute
in
values
;
const
hasPrimary
=
this
.
primaryKeyField
in
values
||
this
.
primaryKeyAttribute
in
values
;
const
instance
=
this
.
build
(
values
);
const
instance
=
this
.
build
(
values
);
const
changed
=
Array
.
from
(
instance
.
_changed
);
if
(
!
options
.
fields
)
{
if
(
!
options
.
fields
)
{
options
.
fields
=
Object
.
keys
(
instance
.
_changed
)
;
options
.
fields
=
changed
;
}
}
return
Promise
.
try
(()
=>
{
return
Promise
.
try
(()
=>
{
...
@@ -2460,7 +2459,7 @@ class Model {
...
@@ -2460,7 +2459,7 @@ class Model {
}
}
}).
then
(()
=>
{
}).
then
(()
=>
{
// Map field names
// Map field names
const
updatedDataValues
=
_
.
pick
(
instance
.
dataValues
,
Object
.
keys
(
instance
.
_changed
)
);
const
updatedDataValues
=
_
.
pick
(
instance
.
dataValues
,
changed
);
const
insertValues
=
Utils
.
mapValueFieldNames
(
instance
.
dataValues
,
Object
.
keys
(
instance
.
rawAttributes
),
this
);
const
insertValues
=
Utils
.
mapValueFieldNames
(
instance
.
dataValues
,
Object
.
keys
(
instance
.
rawAttributes
),
this
);
const
updateValues
=
Utils
.
mapValueFieldNames
(
updatedDataValues
,
options
.
fields
,
this
);
const
updateValues
=
Utils
.
mapValueFieldNames
(
updatedDataValues
,
options
.
fields
,
this
);
const
now
=
Utils
.
now
(
this
.
sequelize
.
options
.
dialect
);
const
now
=
Utils
.
now
(
this
.
sequelize
.
options
.
dialect
);
...
@@ -3477,7 +3476,7 @@ class Model {
...
@@ -3477,7 +3476,7 @@ class Model {
setDataValue
(
key
,
value
)
{
setDataValue
(
key
,
value
)
{
const
originalValue
=
this
.
_previousDataValues
[
key
];
const
originalValue
=
this
.
_previousDataValues
[
key
];
if
(
!
Utils
.
isPrimitive
(
value
)
&&
value
!==
null
||
value
!==
originalValue
)
{
if
(
!
_
.
isEqual
(
value
,
originalValue
)
)
{
this
.
changed
(
key
,
true
);
this
.
changed
(
key
,
true
);
}
}
...
@@ -3654,7 +3653,7 @@ class Model {
...
@@ -3654,7 +3653,7 @@ class Model {
// custom setter should have changed value, get that changed value
// custom setter should have changed value, get that changed value
// TODO: v5 make setters return new value instead of changing internal store
// TODO: v5 make setters return new value instead of changing internal store
const
newValue
=
this
.
dataValues
[
key
];
const
newValue
=
this
.
dataValues
[
key
];
if
(
!
Utils
.
isPrimitive
(
newValue
)
&&
newValue
!==
null
||
newValue
!==
originalValue
)
{
if
(
!
_
.
isEqual
(
newValue
,
originalValue
)
)
{
this
.
_previousDataValues
[
key
]
=
originalValue
;
this
.
_previousDataValues
[
key
]
=
originalValue
;
this
.
changed
(
key
,
true
);
this
.
changed
(
key
,
true
);
}
}
...
@@ -3707,7 +3706,7 @@ class Model {
...
@@ -3707,7 +3706,7 @@ class Model {
// Check for data type type comparators
// Check for data type type comparators
!
(
value
instanceof
Utils
.
SequelizeMethod
)
&&
this
.
constructor
.
_dataTypeChanges
[
key
]
&&
this
.
constructor
.
_dataTypeChanges
[
key
].
call
(
this
,
value
,
originalValue
,
options
)
||
!
(
value
instanceof
Utils
.
SequelizeMethod
)
&&
this
.
constructor
.
_dataTypeChanges
[
key
]
&&
this
.
constructor
.
_dataTypeChanges
[
key
].
call
(
this
,
value
,
originalValue
,
options
)
||
// Check default
// Check default
!
this
.
constructor
.
_dataTypeChanges
[
key
]
&&
(
!
Utils
.
isPrimitive
(
value
)
&&
value
!==
null
||
value
!==
originalValue
)
!
this
.
constructor
.
_dataTypeChanges
[
key
]
&&
!
_
.
isEqual
(
value
,
originalValue
)
)
)
)
{
)
{
this
.
_previousDataValues
[
key
]
=
originalValue
;
this
.
_previousDataValues
[
key
]
=
originalValue
;
...
@@ -3731,23 +3730,42 @@ class Model {
...
@@ -3731,23 +3730,42 @@ class Model {
*
*
* If changed is called without an argument and no keys have changed, it will return `false`.
* If changed is called without an argument and no keys have changed, it will return `false`.
*
*
* Please note that this function will return `false` when a property from a nested (for example JSON) property
* was edited manually, you must call `changed('key', true)` manually in these cases.
* Writing an entirely new object (eg. deep cloned) will be detected.
*
* @example
* ```
* const mdl = await MyModel.findOne();
* mdl.myJsonField.a = 1;
* console.log(mdl.changed()) => false
* mdl.save(); // this will not save anything
* mdl.changed('myJsonField', true);
* console.log(mdl.changed()) => ['myJsonField']
* mdl.save(); // will save
* ```
*
* @param {string} [key] key to check or change status of
* @param {string} [key] key to check or change status of
* @param {any} [value] value to set
* @param {any} [value] value to set
*
*
* @returns {boolean|Array}
* @returns {boolean|Array}
*/
*/
changed
(
key
,
value
)
{
changed
(
key
,
value
)
{
if
(
key
)
{
if
(
key
===
undefined
)
{
if
(
value
!==
undefined
)
{
if
(
this
.
_changed
.
size
>
0
)
{
this
.
_changed
[
key
]
=
value
;
return
Array
.
from
(
this
.
_changed
);
return
this
;
}
}
return
this
.
_changed
[
key
]
||
false
;
return
false
;
}
}
if
(
value
===
true
)
{
const
changed
=
Object
.
keys
(
this
.
dataValues
).
filter
(
key
=>
this
.
changed
(
key
));
this
.
_changed
.
add
(
key
);
return
this
;
return
changed
.
length
?
changed
:
false
;
}
if
(
value
===
false
)
{
this
.
_changed
.
delete
(
key
);
return
this
;
}
return
this
.
_changed
.
has
(
key
);
}
}
/**
/**
...
...
test/unit/instance/changed.test.js
View file @
29c9be3
...
@@ -78,21 +78,18 @@ describe(Support.getTestDialectTeaser('Instance'), () => {
...
@@ -78,21 +78,18 @@ describe(Support.getTestDialectTeaser('Instance'), () => {
expect
(
user
.
changed
(
'birthday'
)).
to
.
equal
(
false
);
expect
(
user
.
changed
(
'birthday'
)).
to
.
equal
(
false
);
});
});
it
(
'should return true for changed JSON with same object'
,
function
()
{
it
(
'should not detect changes when equal'
,
function
()
{
const
user
=
this
.
User
.
build
({
for
(
const
value
of
[
null
,
1
,
'asdf'
,
new
Date
(),
[],
{},
Buffer
.
from
(
''
)])
{
meta
:
{
const
t
=
new
this
.
User
({
city
:
'Copenhagen'
json
:
value
}
},
{
},
{
isNewRecord
:
false
,
isNewRecord
:
false
,
raw
:
true
raw
:
true
});
});
t
.
json
=
value
;
expect
(
t
.
changed
(
'json'
)).
to
.
be
.
false
;
const
meta
=
user
.
get
(
'meta'
);
expect
(
t
.
changed
()).
to
.
be
.
false
;
meta
.
city
=
'Stockholm'
;
}
user
.
set
(
'meta'
,
meta
);
expect
(
user
.
changed
(
'meta'
)).
to
.
equal
(
true
);
});
});
it
(
'should return true for JSON dot.separated key with changed values'
,
function
()
{
it
(
'should return true for JSON dot.separated key with changed values'
,
function
()
{
...
...
Write
Preview
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment