Implement intent hook `before delete`

Methods `DAO.deleteAll` and `DAO.prototype.delete` now invoke
`before delete` hook too. The hook receives `ctx.where` describing
models to be deleted.
This commit is contained in:
Miroslav Bajtoš 2015-01-29 10:09:01 +01:00
parent 842e543bf7
commit 370966df99
2 changed files with 104 additions and 2 deletions

View File

@ -995,7 +995,11 @@ DataAccessObject.remove = DataAccessObject.deleteAll = DataAccessObject.destroyA
{ Model: Model, query: query },
function(err, ctx) {
if (err) return cb(err);
doDelete(ctx.query.where);
var context = { Model: Model, where: ctx.query.where };
Model.notifyObserversOf('before delete', context, function(err, ctx) {
if (err) return cb(err);
doDelete(ctx.where);
});
});
}
@ -1311,7 +1315,13 @@ DataAccessObject.prototype.remove =
{ Model: Model, query: byIdQuery(Model, id) },
function(err, ctx) {
if (err) return cb(err);
doDeleteInstance(ctx.query.where);
Model.notifyObserversOf(
'before delete',
{ Model: Model, where: ctx.query.where },
function(err, ctx) {
if (err) return cb(err);
doDeleteInstance(ctx.where);
});
});
function doDeleteInstance(where) {

View File

@ -893,6 +893,57 @@ module.exports = function(dataSource, should) {
});
});
it('triggers `before delete` hook with query', function(done) {
TestModel.observe('before delete', pushContextAndNext());
TestModel.deleteAll({ name: existingInstance.name }, function(err) {
if (err) return done(err);
observedContexts.should.eql(aTestModelCtx({
where: { name: existingInstance.name }
}));
done();
});
});
it('triggers `before delete` hook without query', function(done) {
TestModel.observe('before delete', pushContextAndNext());
TestModel.deleteAll(function(err) {
if (err) return done(err);
observedContexts.should.eql(aTestModelCtx({ where: {} }));
done();
});
});
it('applies updates from `before delete` hook', function(done) {
TestModel.observe('before delete', function(ctx, next) {
ctx.where = { id: { neq: existingInstance.id } };
next();
});
TestModel.deleteAll(function(err) {
if (err) return done(err);
findTestModels(function(err, list) {
if (err) return done(err);
(list || []).map(get('id')).should.eql([existingInstance.id]);
done();
});
});
});
it('aborts when `before delete` hook fails', function(done) {
TestModel.observe('before delete', nextWithError(expectedError));
TestModel.deleteAll(function(err, list) {
[err].should.eql([expectedError]);
TestModel.findById(existingInstance.id, function(err, inst) {
if (err) return done(err);
(inst ? inst.toObject() : 'null').should.eql(existingInstance.toObject());
done();
});
});
});
it('triggers `after delete` hook without query', function(done) {
TestModel.observe('after delete', pushContextAndNext());
@ -954,6 +1005,47 @@ module.exports = function(dataSource, should) {
});
});
it('triggers `before delete` hook', function(done) {
TestModel.observe('before delete', pushContextAndNext());
existingInstance.delete(function(err) {
if (err) return done(err);
observedContexts.should.eql(aTestModelCtx({
where: { id: existingInstance.id }
}));
done();
});
});
it('applies updated from `before delete` hook', function(done) {
TestModel.observe('before delete', function(ctx, next) {
ctx.where = { id: { neq: existingInstance.id } };
next();
});
existingInstance.delete(function(err) {
if (err) return done(err);
findTestModels(function(err, list) {
if (err) return done(err);
(list || []).map(get('id')).should.eql([existingInstance.id]);
done();
});
});
});
it('aborts when `before delete` hook fails', function(done) {
TestModel.observe('before delete', nextWithError(expectedError));
existingInstance.delete(function(err, list) {
[err].should.eql([expectedError]);
TestModel.findById(existingInstance.id, function(err, inst) {
if (err) return done(err);
(inst ? inst.toObject() : 'null').should.eql(existingInstance.toObject());
done();
});
});
});
it('triggers `after delete` hook', function(done) {
TestModel.observe('after delete', pushContextAndNext());