fix: regression on Operation Hooks
Fix the regression introduced by 9af79cf51a
where updateAttributes
and replaceAttributes was incorrectly handling the response returned
by the database.
This commit restores the old behaviour where `context.data` is updated
only by a connector-provided function and reverts an incorrect change
of a test file made as part of the faulty fix.
Besides the fixes, this patch also renames `data` to `dbResponse` and
add comments explaining the structure of the response object for more
clarity.
This commit is contained in:
parent
da728b8d70
commit
9bd7f8d02f
22
lib/dao.js
22
lib/dao.js
|
@ -3087,11 +3087,15 @@ DataAccessObject.replaceById = function(id, data, options, cb) {
|
||||||
var typedData = convertSubsetOfPropertiesByType(inst, data);
|
var typedData = convertSubsetOfPropertiesByType(inst, data);
|
||||||
context.data = typedData;
|
context.data = typedData;
|
||||||
|
|
||||||
function replaceCallback(err, data) {
|
// Depending on the connector, the database response can
|
||||||
|
// contain information about the updated record(s). This object
|
||||||
|
// has usually database-specific structure and does not match
|
||||||
|
// model properties. For example, MySQL returns OkPacket:
|
||||||
|
// {fieldCount, affectedRows, insertId, /*...*/, changedRows}
|
||||||
|
function replaceCallback(err, dbResponse) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
context.data = data;
|
|
||||||
if (typeof connector.generateContextData === 'function') {
|
if (typeof connector.generateContextData === 'function') {
|
||||||
context = connector.generateContextData(context, data);
|
context = connector.generateContextData(context, dbResponse);
|
||||||
}
|
}
|
||||||
var ctx = {
|
var ctx = {
|
||||||
Model: Model,
|
Model: Model,
|
||||||
|
@ -3138,6 +3142,8 @@ DataAccessObject.replaceById = function(id, data, options, cb) {
|
||||||
};
|
};
|
||||||
Model.notifyObserversOf('persist', ctx, function(err) {
|
Model.notifyObserversOf('persist', ctx, function(err) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
// apply updates made by "persist" observers
|
||||||
|
context.data = ctx.data;
|
||||||
invokeConnectorMethod(connector, 'replaceById', Model, [id, Model._forDB(ctx.data)],
|
invokeConnectorMethod(connector, 'replaceById', Model, [id, Model._forDB(ctx.data)],
|
||||||
options, replaceCallback);
|
options, replaceCallback);
|
||||||
});
|
});
|
||||||
|
@ -3281,11 +3287,13 @@ function(data, options, cb) {
|
||||||
var typedData = convertSubsetOfPropertiesByType(inst, data);
|
var typedData = convertSubsetOfPropertiesByType(inst, data);
|
||||||
context.data = typedData;
|
context.data = typedData;
|
||||||
|
|
||||||
function updateAttributesCallback(err, data) {
|
// Depending on the connector, the database response can
|
||||||
|
// contain information about the updated record(s), but also
|
||||||
|
// just a number of updated rows (e.g. {count: 1} for MySQL).
|
||||||
|
function updateAttributesCallback(err, dbResponse) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
context.data = data;
|
|
||||||
if (typeof connector.generateContextData === 'function') {
|
if (typeof connector.generateContextData === 'function') {
|
||||||
context = connector.generateContextData(context, data);
|
context = connector.generateContextData(context, dbResponse);
|
||||||
}
|
}
|
||||||
var ctx = {
|
var ctx = {
|
||||||
Model: Model,
|
Model: Model,
|
||||||
|
@ -3336,6 +3344,8 @@ function(data, options, cb) {
|
||||||
};
|
};
|
||||||
Model.notifyObserversOf('persist', ctx, function(err) {
|
Model.notifyObserversOf('persist', ctx, function(err) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
// apply updates made by "persist" observers
|
||||||
|
context.data = ctx.data;
|
||||||
invokeConnectorMethod(connector, 'updateAttributes', Model,
|
invokeConnectorMethod(connector, 'updateAttributes', Model,
|
||||||
[getIdValue(Model, inst), Model._forDB(ctx.data)],
|
[getIdValue(Model, inst), Model._forDB(ctx.data)],
|
||||||
options, updateAttributesCallback);
|
options, updateAttributesCallback);
|
||||||
|
|
|
@ -1529,7 +1529,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
ctxRecorder.records.should.eql(aCtxForModel(TestModel, {
|
ctxRecorder.records.should.eql(aCtxForModel(TestModel, {
|
||||||
data: {id: existingInstance.id, name: 'changed'},
|
data: {name: 'changed'},
|
||||||
isNewInstance: false,
|
isNewInstance: false,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -2765,6 +2765,14 @@ module.exports = function(dataSource, should, connectorCapabilities) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('triggers `persist` hook', function(done) {
|
it('triggers `persist` hook', function(done) {
|
||||||
|
// "extra" property is undefined by default. As a result,
|
||||||
|
// NoSQL connectors omit this property from the data. Because
|
||||||
|
// SQL connectors store it as null, we have different results
|
||||||
|
// depending on the database used.
|
||||||
|
// By enabling "persistUndefinedAsNull", we force NoSQL connectors
|
||||||
|
// to store unset properties using "null" value and thus match SQL.
|
||||||
|
TestModel.settings.persistUndefinedAsNull = true;
|
||||||
|
|
||||||
TestModel.observe('persist', ctxRecorder.recordAndNext());
|
TestModel.observe('persist', ctxRecorder.recordAndNext());
|
||||||
|
|
||||||
existingInstance.name = 'replaced name';
|
existingInstance.name = 'replaced name';
|
||||||
|
@ -2779,11 +2787,12 @@ module.exports = function(dataSource, should, connectorCapabilities) {
|
||||||
data: {
|
data: {
|
||||||
id: existingInstance.id,
|
id: existingInstance.id,
|
||||||
name: 'replaced name',
|
name: 'replaced name',
|
||||||
|
extra: null,
|
||||||
},
|
},
|
||||||
currentInstance: {
|
currentInstance: {
|
||||||
id: existingInstance.id,
|
id: existingInstance.id,
|
||||||
name: 'replaced name',
|
name: 'replaced name',
|
||||||
extra: undefined,
|
extra: null,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue