Improve instance-level operation hooks
"before delete" and "after delete" hooks receive `ctx.instance` when a single model is being deleted. "before save" hook receives `ctx.currentInstance` when triggered by `prototype.updateAttributes()`. Note that "after save" hook triggered by `prototype.updateAttributes()` already provides `ctx.instance`.
This commit is contained in:
parent
2a24273b4f
commit
8605da3ac6
30
lib/dao.js
30
lib/dao.js
|
@ -1732,18 +1732,23 @@ DataAccessObject.prototype.remove =
|
|||
assert(typeof options === 'object', 'The options argument should be an object');
|
||||
assert(typeof cb === 'function', 'The cb argument should be a function');
|
||||
|
||||
var self = this;
|
||||
var inst = this;
|
||||
var Model = this.constructor;
|
||||
var id = getIdValue(this.constructor, this);
|
||||
var hookState = {};
|
||||
|
||||
var context = {
|
||||
Model: Model, query: byIdQuery(Model, id), hookState: hookState
|
||||
Model: Model, query: byIdQuery(Model, id), hookState: hookState
|
||||
};
|
||||
|
||||
Model.notifyObserversOf('access', context, function(err, ctx) {
|
||||
if (err) return cb(err);
|
||||
var context = { Model: Model, where: ctx.query.where, hookState: hookState };
|
||||
var context = {
|
||||
Model: Model,
|
||||
where: ctx.query.where,
|
||||
instance: inst,
|
||||
hookState: hookState
|
||||
};
|
||||
Model.notifyObserversOf('before delete', context, function(err, ctx) {
|
||||
if (err) return cb(err);
|
||||
doDeleteInstance(ctx.where);
|
||||
|
@ -1757,7 +1762,12 @@ DataAccessObject.prototype.remove =
|
|||
// We must switch to full query-based delete.
|
||||
Model.deleteAll(where, { notify: false }, function(err) {
|
||||
if (err) return cb(err);
|
||||
var context = { Model: Model, where: where, hookState: hookState };
|
||||
var context = {
|
||||
Model: Model,
|
||||
where: where,
|
||||
instance: inst,
|
||||
hookState: hookState
|
||||
};
|
||||
Model.notifyObserversOf('after delete', context, function(err) {
|
||||
cb(err);
|
||||
if (!err) Model.emit('deleted', id);
|
||||
|
@ -1766,14 +1776,19 @@ DataAccessObject.prototype.remove =
|
|||
return;
|
||||
}
|
||||
|
||||
self.trigger('destroy', function (destroyed) {
|
||||
self._adapter().destroy(self.constructor.modelName, id, function (err) {
|
||||
inst.trigger('destroy', function (destroyed) {
|
||||
inst._adapter().destroy(inst.constructor.modelName, id, function (err) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
destroyed(function () {
|
||||
var context = { Model: Model, where: where, hookState: hookState };
|
||||
var context = {
|
||||
Model: Model,
|
||||
where: where,
|
||||
instance: inst,
|
||||
hookState: hookState
|
||||
};
|
||||
Model.notifyObserversOf('after delete', context, function(err) {
|
||||
cb(err);
|
||||
if (!err) Model.emit('deleted', id);
|
||||
|
@ -1893,6 +1908,7 @@ DataAccessObject.prototype.updateAttributes = function updateAttributes(data, op
|
|||
Model: Model,
|
||||
where: byIdQuery(Model, getIdValue(Model, inst)).where,
|
||||
data: data,
|
||||
currentInstance: inst,
|
||||
hookState: hookState
|
||||
};
|
||||
|
||||
|
|
|
@ -535,12 +535,15 @@ module.exports = function(dataSource, should) {
|
|||
it('triggers `before save` hook', function(done) {
|
||||
TestModel.observe('before save', pushContextAndNext());
|
||||
|
||||
existingInstance.name = 'changed';
|
||||
var currentInstance = deepCloneToObject(existingInstance);
|
||||
|
||||
existingInstance.updateAttributes({ name: 'changed' }, function(err) {
|
||||
if (err) return done(err);
|
||||
existingInstance.name.should.equal('changed');
|
||||
observedContexts.should.eql(aTestModelCtx({
|
||||
where: { id: existingInstance.id },
|
||||
data: { name: 'changed' }
|
||||
data: { name: 'changed' },
|
||||
currentInstance: currentInstance
|
||||
}));
|
||||
done();
|
||||
});
|
||||
|
@ -736,10 +739,24 @@ module.exports = function(dataSource, should) {
|
|||
{ id: existingInstance.id, name: 'updated name' },
|
||||
function(err, instance) {
|
||||
if (err) return done(err);
|
||||
observedContexts.should.eql(aTestModelCtx({
|
||||
where: { id: existingInstance.id },
|
||||
data: { id: existingInstance.id, name: 'updated name' }
|
||||
}));
|
||||
if (dataSource.connector.updateOrCreate) {
|
||||
// Atomic implementations of `updateOrCreate` cannot
|
||||
// provide full instance as that depends on whether
|
||||
// UPDATE or CREATE will be triggered
|
||||
observedContexts.should.eql(aTestModelCtx({
|
||||
where: { id: existingInstance.id },
|
||||
data: { id: existingInstance.id, name: 'updated name' }
|
||||
}));
|
||||
} else {
|
||||
// currentInstance is set, because a non-atomic `updateOrCreate`
|
||||
// will use `prototype.updateAttributes` internally, which
|
||||
// exposes this to the context
|
||||
observedContexts.should.eql(aTestModelCtx({
|
||||
where: { id: existingInstance.id },
|
||||
data: { id: existingInstance.id, name: 'updated name' },
|
||||
currentInstance: existingInstance
|
||||
}));
|
||||
}
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -1026,7 +1043,8 @@ module.exports = function(dataSource, should) {
|
|||
existingInstance.delete(function(err) {
|
||||
if (err) return done(err);
|
||||
observedContexts.should.eql(aTestModelCtx({
|
||||
where: { id: existingInstance.id }
|
||||
where: { id: existingInstance.id },
|
||||
instance: existingInstance
|
||||
}));
|
||||
done();
|
||||
});
|
||||
|
@ -1068,7 +1086,8 @@ module.exports = function(dataSource, should) {
|
|||
existingInstance.delete(function(err) {
|
||||
if (err) return done(err);
|
||||
observedContexts.should.eql(aTestModelCtx({
|
||||
where: { id: existingInstance.id }
|
||||
where: { id: existingInstance.id },
|
||||
instance: existingInstance
|
||||
}));
|
||||
done();
|
||||
});
|
||||
|
@ -1109,11 +1128,13 @@ module.exports = function(dataSource, should) {
|
|||
observedContexts.should.eql([
|
||||
aTestModelCtx({
|
||||
hookState: { foo: 'bar', test: true },
|
||||
where: { id: '1' }
|
||||
where: { id: '1' },
|
||||
instance: existingInstance
|
||||
}),
|
||||
aTestModelCtx({
|
||||
hookState: { foo: 'BAR', test: true },
|
||||
where: { id: '1' }
|
||||
where: { id: '1' },
|
||||
instance: existingInstance
|
||||
})
|
||||
]);
|
||||
done();
|
||||
|
|
Loading…
Reference in New Issue