Merge pull request #65 from strongloop/feature/change-hook
Add change / delete events
This commit is contained in:
commit
61a54da418
22
lib/dao.js
22
lib/dao.js
|
@ -126,6 +126,7 @@ DataAccessObject.create = function (data, callback) {
|
||||||
function modelCreated() {
|
function modelCreated() {
|
||||||
if (--wait === 0) {
|
if (--wait === 0) {
|
||||||
callback(gotError ? errors : null, instances);
|
callback(gotError ? errors : null, instances);
|
||||||
|
if(!gotError) instances.forEach(Model.emit.bind('changed'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,6 +169,7 @@ DataAccessObject.create = function (data, callback) {
|
||||||
saveDone.call(obj, function () {
|
saveDone.call(obj, function () {
|
||||||
createDone.call(obj, function () {
|
createDone.call(obj, function () {
|
||||||
callback(err, obj);
|
callback(err, obj);
|
||||||
|
if(!err) Model.emit('changed', obj);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}, obj);
|
}, obj);
|
||||||
|
@ -627,6 +629,7 @@ DataAccessObject.remove =
|
||||||
DataAccessObject.deleteAll =
|
DataAccessObject.deleteAll =
|
||||||
DataAccessObject.destroyAll = function destroyAll(where, cb) {
|
DataAccessObject.destroyAll = function destroyAll(where, cb) {
|
||||||
if (stillConnecting(this.getDataSource(), this, arguments)) return;
|
if (stillConnecting(this.getDataSource(), this, arguments)) return;
|
||||||
|
var Model = this;
|
||||||
|
|
||||||
if (!cb && 'function' === typeof where) {
|
if (!cb && 'function' === typeof where) {
|
||||||
cb = where;
|
cb = where;
|
||||||
|
@ -635,6 +638,7 @@ DataAccessObject.remove =
|
||||||
if (!where) {
|
if (!where) {
|
||||||
this.getDataSource().connector.destroyAll(this.modelName, function (err, data) {
|
this.getDataSource().connector.destroyAll(this.modelName, function (err, data) {
|
||||||
cb && cb(err, data);
|
cb && cb(err, data);
|
||||||
|
if(!err) Model.emit('deletedAll');
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
} else {
|
} else {
|
||||||
// Support an optional where object
|
// Support an optional where object
|
||||||
|
@ -642,6 +646,7 @@ DataAccessObject.remove =
|
||||||
where = this._coerce(where);
|
where = this._coerce(where);
|
||||||
this.getDataSource().connector.destroyAll(this.modelName, where, function (err, data) {
|
this.getDataSource().connector.destroyAll(this.modelName, where, function (err, data) {
|
||||||
cb && cb(err, data);
|
cb && cb(err, data);
|
||||||
|
if(!err) Model.emit('deletedAll', where);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -655,11 +660,13 @@ DataAccessObject.removeById =
|
||||||
DataAccessObject.deleteById =
|
DataAccessObject.deleteById =
|
||||||
DataAccessObject.destroyById = function deleteById(id, cb) {
|
DataAccessObject.destroyById = function deleteById(id, cb) {
|
||||||
if (stillConnecting(this.getDataSource(), this, arguments)) return;
|
if (stillConnecting(this.getDataSource(), this, arguments)) return;
|
||||||
|
var Model = this;
|
||||||
|
|
||||||
this.getDataSource().connector.destroy(this.modelName, id, function (err) {
|
this.getDataSource().connector.destroy(this.modelName, id, function (err) {
|
||||||
if ('function' === typeof cb) {
|
if ('function' === typeof cb) {
|
||||||
cb(err);
|
cb(err);
|
||||||
}
|
}
|
||||||
|
if(!err) Model.emit('deleted', id);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -704,6 +711,7 @@ setRemoting(DataAccessObject.count, {
|
||||||
*/
|
*/
|
||||||
DataAccessObject.prototype.save = function (options, callback) {
|
DataAccessObject.prototype.save = function (options, callback) {
|
||||||
if (stillConnecting(this.getDataSource(), this, arguments)) return;
|
if (stillConnecting(this.getDataSource(), this, arguments)) return;
|
||||||
|
var Model = this.constructor;
|
||||||
|
|
||||||
if (typeof options == 'function') {
|
if (typeof options == 'function') {
|
||||||
callback = options;
|
callback = options;
|
||||||
|
@ -760,6 +768,9 @@ DataAccessObject.prototype.save = function (options, callback) {
|
||||||
updateDone.call(inst, function () {
|
updateDone.call(inst, function () {
|
||||||
saveDone.call(inst, function () {
|
saveDone.call(inst, function () {
|
||||||
callback(err, inst);
|
callback(err, inst);
|
||||||
|
if(!err) {
|
||||||
|
Model.emit('changed', inst);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -789,15 +800,18 @@ DataAccessObject.prototype.remove =
|
||||||
DataAccessObject.prototype.delete =
|
DataAccessObject.prototype.delete =
|
||||||
DataAccessObject.prototype.destroy = function (cb) {
|
DataAccessObject.prototype.destroy = function (cb) {
|
||||||
if (stillConnecting(this.getDataSource(), this, arguments)) return;
|
if (stillConnecting(this.getDataSource(), this, arguments)) return;
|
||||||
|
var Model = this.constructor;
|
||||||
|
var id = getIdValue(this.constructor, this);
|
||||||
|
|
||||||
this.trigger('destroy', function (destroyed) {
|
this.trigger('destroy', function (destroyed) {
|
||||||
this._adapter().destroy(this.constructor.modelName, getIdValue(this.constructor, this), function (err) {
|
this._adapter().destroy(this.constructor.modelName, id, function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return cb(err);
|
return cb(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
destroyed(function () {
|
destroyed(function () {
|
||||||
if (cb) cb();
|
if (cb) cb();
|
||||||
|
Model.emit('deleted', id);
|
||||||
});
|
});
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
});
|
});
|
||||||
|
@ -831,7 +845,8 @@ DataAccessObject.prototype.updateAttributes = function updateAttributes(data, cb
|
||||||
if (stillConnecting(this.getDataSource(), this, arguments)) return;
|
if (stillConnecting(this.getDataSource(), this, arguments)) return;
|
||||||
|
|
||||||
var inst = this;
|
var inst = this;
|
||||||
var model = this.constructor.modelName;
|
var Model = this.constructor
|
||||||
|
var model = Model.modelName;
|
||||||
|
|
||||||
if (typeof data === 'function') {
|
if (typeof data === 'function') {
|
||||||
cb = data;
|
cb = data;
|
||||||
|
@ -870,7 +885,8 @@ DataAccessObject.prototype.updateAttributes = function updateAttributes(data, cb
|
||||||
}
|
}
|
||||||
done.call(inst, function () {
|
done.call(inst, function () {
|
||||||
saveDone.call(inst, function () {
|
saveDone.call(inst, function () {
|
||||||
cb(err, inst);
|
if(cb) cb(err, inst);
|
||||||
|
if(!err) Model.emit('changed', inst);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
var should = require('./init.js');
|
||||||
|
|
||||||
|
describe('events', function() {
|
||||||
|
beforeEach(function(done) {
|
||||||
|
var test = this;
|
||||||
|
this.db = getSchema();
|
||||||
|
this.TestModel = this.db.define('TestModel');
|
||||||
|
this.db.automigrate(function(err) {
|
||||||
|
if(err) return done(err);
|
||||||
|
test.TestModel.create(function(err, inst) {
|
||||||
|
if(err) return done(err);
|
||||||
|
test.inst = inst;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.shouldEmitEvent = function(eventName, listener, done) {
|
||||||
|
var timeout = setTimeout(function() {
|
||||||
|
done(new Error('did not emit ' + eventName));
|
||||||
|
}, 100);
|
||||||
|
this.TestModel.on(eventName, function() {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
listener.apply(this, arguments);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('changed', function() {
|
||||||
|
it('should be emitted after save', function(done) {
|
||||||
|
var model = new this.TestModel({name: 'foobar'});
|
||||||
|
this.shouldEmitEvent('changed', assertValidChangedArgs, done);
|
||||||
|
model.save();
|
||||||
|
});
|
||||||
|
it('should be emitted after upsert', function(done) {
|
||||||
|
this.shouldEmitEvent('changed', assertValidChangedArgs, done);
|
||||||
|
this.TestModel.upsert({name: 'batbaz'});
|
||||||
|
});
|
||||||
|
it('should be emitted after create', function(done) {
|
||||||
|
this.shouldEmitEvent('changed', assertValidChangedArgs, done);
|
||||||
|
this.TestModel.create({name: '...'});
|
||||||
|
});
|
||||||
|
it('should be emitted after updateAttributes', function(done) {
|
||||||
|
var test = this;
|
||||||
|
this.TestModel.create({name: 'bazzy'}, function(err, model) {
|
||||||
|
// prevent getting the changed event from "create"
|
||||||
|
process.nextTick(function() {
|
||||||
|
test.shouldEmitEvent('changed', assertValidChangedArgs, done);
|
||||||
|
model.updateAttributes({name: 'foo'});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('deleted', function() {
|
||||||
|
it('should be emitted after destroy', function(done) {
|
||||||
|
this.shouldEmitEvent('deleted', assertValidDeletedArgs, done);
|
||||||
|
this.inst.destroy();
|
||||||
|
});
|
||||||
|
it('should be emitted after deleteById', function(done) {
|
||||||
|
this.shouldEmitEvent('deleted', assertValidDeletedArgs, done);
|
||||||
|
this.TestModel.deleteById(this.inst.id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('deletedAll', function() {
|
||||||
|
it('should be emitted after destroyAll', function(done) {
|
||||||
|
this.shouldEmitEvent('deletedAll', function(where) {
|
||||||
|
where.name.should.equal('foo');
|
||||||
|
}, done);
|
||||||
|
this.TestModel.destroyAll({name: 'foo'});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function assertValidChangedArgs(obj) {
|
||||||
|
obj.should.have.property('id');
|
||||||
|
}
|
||||||
|
|
||||||
|
function assertValidDeletedArgs(id) {
|
||||||
|
id.should.be.ok;
|
||||||
|
}
|
|
@ -402,6 +402,8 @@ describe('hooks', function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function addHooks(name, done) {
|
function addHooks(name, done) {
|
||||||
var called = false, random = String(Math.floor(Math.random() * 1000));
|
var called = false, random = String(Math.floor(Math.random() * 1000));
|
||||||
User['before' + name] = function (next, data) {
|
User['before' + name] = function (next, data) {
|
||||||
|
|
Loading…
Reference in New Issue