Add ctx.isNewInstance for "save" hooks
"before save" hooks provide "ctx.isNewInstance" whenever "ctx.instance" is set. Possible values: - true for all CREATE operations - false for all UPDATE operations - undefined for "prototype.save" "after save" hooks provide "ctx.isNewInstance" whenever "ctx.instance" is set. Possible values: - true after all CREATE operations - false after all UPDATE operations - undefined after "updateOrCreate" and "save" Note: both "updateOrCreate" and "prototype.updateAttributes" don't provide `ctx.instance` to "before save" hooks, therefore `ctx.isNewInstance` it not provided either.
This commit is contained in:
parent
ae3dc3cec2
commit
ffcaa4e76e
|
@ -225,11 +225,13 @@ Memory.prototype.updateOrCreate = function (model, data, callback) {
|
|||
var self = this;
|
||||
this.exists(model, self.getIdValue(model, data), function (err, exists) {
|
||||
if (exists) {
|
||||
self.save(model, data, callback);
|
||||
self.save(model, data, function(err, data) {
|
||||
callback(err, data, { isNewInstance: false });
|
||||
});
|
||||
} else {
|
||||
self.create(model, data, function (err, id) {
|
||||
self.setIdValue(model, data, id);
|
||||
callback(err, data);
|
||||
callback(err, data, { isNewInstance: true });
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -244,7 +246,9 @@ Memory.prototype.save = function save(model, data, callback) {
|
|||
data = merge(modelData, data);
|
||||
}
|
||||
this.collection(model)[id] = serialize(data);
|
||||
this.saveToFile(data, callback);
|
||||
this.saveToFile(data, function(err) {
|
||||
callback(err, data, { isNewInstance: !modelData });
|
||||
});
|
||||
};
|
||||
|
||||
Memory.prototype.exists = function exists(model, id, callback) {
|
||||
|
@ -462,12 +466,12 @@ function applyFilter(filter) {
|
|||
if ('neq' in example) {
|
||||
return compare(example.neq, value) !== 0;
|
||||
}
|
||||
|
||||
|
||||
if ('between' in example ) {
|
||||
return ( testInEquality({gte:example.between[0]}, value) &&
|
||||
return ( testInEquality({gte:example.between[0]}, value) &&
|
||||
testInEquality({lte:example.between[1]}, value) );
|
||||
}
|
||||
|
||||
|
||||
if (example.like || example.nlike) {
|
||||
|
||||
var like = example.like || example.nlike;
|
||||
|
|
53
lib/dao.js
53
lib/dao.js
|
@ -231,7 +231,12 @@ DataAccessObject.create = function (data, options, cb) {
|
|||
Model = this.lookupModel(data); // data-specific
|
||||
if (Model !== obj.constructor) obj = new Model(data);
|
||||
|
||||
var context = { Model: Model, instance: obj, hookState: hookState };
|
||||
var context = {
|
||||
Model: Model,
|
||||
instance: obj,
|
||||
isNewInstance: true,
|
||||
hookState: hookState
|
||||
};
|
||||
Model.notifyObserversOf('before save', context, function(err) {
|
||||
if (err) return cb(err);
|
||||
|
||||
|
@ -270,7 +275,12 @@ DataAccessObject.create = function (data, options, cb) {
|
|||
if (err) {
|
||||
return cb(err, obj);
|
||||
}
|
||||
var context = { Model: Model, instance: obj, hookState: hookState };
|
||||
var context = {
|
||||
Model: Model,
|
||||
instance: obj,
|
||||
isNewInstance: true,
|
||||
hookState: hookState
|
||||
};
|
||||
Model.notifyObserversOf('after save', context, function(err) {
|
||||
cb(err, obj);
|
||||
if(!err) Model.emit('changed', obj);
|
||||
|
@ -390,7 +400,7 @@ DataAccessObject.updateOrCreate = DataAccessObject.upsert = function upsert(data
|
|||
self.getDataSource().connector
|
||||
.updateOrCreate(Model.modelName, update, done);
|
||||
|
||||
function done(err, data) {
|
||||
function done(err, data, result) {
|
||||
var obj;
|
||||
if (data && !(data instanceof Model)) {
|
||||
inst._initProperties(data, { persisted: true });
|
||||
|
@ -404,7 +414,12 @@ DataAccessObject.updateOrCreate = DataAccessObject.upsert = function upsert(data
|
|||
Model.emit('changed', inst);
|
||||
}
|
||||
} else {
|
||||
var context = { Model: Model, instance: obj, hookState: hookState };
|
||||
var context = {
|
||||
Model: Model,
|
||||
instance: obj,
|
||||
isNewInstance: result ? result.isNewInstance : undefined,
|
||||
hookState: hookState
|
||||
};
|
||||
Model.notifyObserversOf('after save', context, function(err) {
|
||||
cb(err, obj);
|
||||
if(!err) {
|
||||
|
@ -505,7 +520,12 @@ DataAccessObject.findOrCreate = function findOrCreate(query, data, options, cb)
|
|||
}
|
||||
|
||||
if (created) {
|
||||
var context = { Model: Model, instance: obj, hookState: hookState };
|
||||
var context = {
|
||||
Model: Model,
|
||||
instance: obj,
|
||||
isNewInstance: true,
|
||||
hookState: hookState
|
||||
};
|
||||
Model.notifyObserversOf('after save', context, function(err) {
|
||||
if (cb.promise) {
|
||||
cb(err, [obj, created]);
|
||||
|
@ -551,7 +571,12 @@ DataAccessObject.findOrCreate = function findOrCreate(query, data, options, cb)
|
|||
Model.applyProperties(enforced, obj);
|
||||
obj.setAttributes(enforced);
|
||||
|
||||
var context = { Model: Model, instance: obj, hookState: hookState };
|
||||
var context = {
|
||||
Model: Model,
|
||||
instance: obj,
|
||||
isNewInstance: true,
|
||||
hookState: hookState
|
||||
};
|
||||
Model.notifyObserversOf('before save', context, function(err, ctx) {
|
||||
if (err) return cb(err);
|
||||
|
||||
|
@ -1562,12 +1587,17 @@ DataAccessObject.prototype.save = function (options, cb) {
|
|||
inst.trigger('save', function (saveDone) {
|
||||
inst.trigger('update', function (updateDone) {
|
||||
data = removeUndefined(data);
|
||||
inst._adapter().save(modelName, inst.constructor._forDB(data), function (err) {
|
||||
inst._adapter().save(modelName, inst.constructor._forDB(data), function (err, data, result) {
|
||||
if (err) {
|
||||
return cb(err, inst);
|
||||
}
|
||||
inst._initProperties(data, { persisted: true });
|
||||
var context = { Model: Model, instance: inst, hookState: hookState };
|
||||
var context = {
|
||||
Model: Model,
|
||||
instance: inst,
|
||||
isNewInstance: result && result.isNewInstance,
|
||||
hookState: hookState
|
||||
};
|
||||
Model.notifyObserversOf('after save', context, function(err) {
|
||||
if (err) return cb(err, inst);
|
||||
updateDone.call(inst, function () {
|
||||
|
@ -1959,7 +1989,12 @@ DataAccessObject.prototype.updateAttributes = function updateAttributes(data, op
|
|||
done.call(inst, function () {
|
||||
saveDone.call(inst, function () {
|
||||
if (err) return cb(err, inst);
|
||||
var context = { Model: Model, instance: inst, hookState: hookState };
|
||||
var context = {
|
||||
Model: Model,
|
||||
instance: inst,
|
||||
isNewInstance: false,
|
||||
hookState: hookState
|
||||
};
|
||||
Model.notifyObserversOf('after save', context, function(err) {
|
||||
if(!err) Model.emit('changed', inst);
|
||||
cb(err, inst);
|
||||
|
|
|
@ -116,11 +116,14 @@ module.exports = function(dataSource, should) {
|
|||
|
||||
TestModel.create({ name: 'created' }, function(err, instance) {
|
||||
if (err) return done(err);
|
||||
observedContexts.should.eql(aTestModelCtx({ instance: {
|
||||
id: instance.id,
|
||||
name: 'created',
|
||||
extra: undefined
|
||||
}}));
|
||||
observedContexts.should.eql(aTestModelCtx({
|
||||
instance: {
|
||||
id: instance.id,
|
||||
name: 'created',
|
||||
extra: undefined
|
||||
},
|
||||
isNewInstance: true
|
||||
}));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -161,10 +164,12 @@ module.exports = function(dataSource, should) {
|
|||
});
|
||||
observedContexts.should.eql([
|
||||
aTestModelCtx({
|
||||
instance: { id: list[0].id, name: '1', extra: undefined }
|
||||
instance: { id: list[0].id, name: '1', extra: undefined },
|
||||
isNewInstance: true
|
||||
}),
|
||||
aTestModelCtx({
|
||||
instance: { id: list[1].id, name: '2', extra: undefined }
|
||||
instance: { id: list[1].id, name: '2', extra: undefined },
|
||||
isNewInstance: true
|
||||
}),
|
||||
]);
|
||||
done();
|
||||
|
@ -186,11 +191,14 @@ module.exports = function(dataSource, should) {
|
|||
|
||||
TestModel.create({ name: 'created' }, function(err, instance) {
|
||||
if (err) return done(err);
|
||||
observedContexts.should.eql(aTestModelCtx({ instance: {
|
||||
id: instance.id,
|
||||
name: 'created',
|
||||
extra: undefined
|
||||
}}));
|
||||
observedContexts.should.eql(aTestModelCtx({
|
||||
instance: {
|
||||
id: instance.id,
|
||||
name: 'created',
|
||||
extra: undefined
|
||||
},
|
||||
isNewInstance: true
|
||||
}));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -231,10 +239,12 @@ module.exports = function(dataSource, should) {
|
|||
});
|
||||
observedContexts.should.eql([
|
||||
aTestModelCtx({
|
||||
instance: { id: list[0].id, name: '1', extra: undefined }
|
||||
instance: { id: list[0].id, name: '1', extra: undefined },
|
||||
isNewInstance: true
|
||||
}),
|
||||
aTestModelCtx({
|
||||
instance: { id: list[1].id, name: '2', extra: undefined }
|
||||
instance: { id: list[1].id, name: '2', extra: undefined },
|
||||
isNewInstance: true
|
||||
}),
|
||||
]);
|
||||
done();
|
||||
|
@ -263,7 +273,8 @@ module.exports = function(dataSource, should) {
|
|||
list.map(get('name')).should.eql(['ok', 'fail']);
|
||||
|
||||
observedContexts.should.eql(aTestModelCtx({
|
||||
instance: { id: list[0].id, name: 'ok', extra: undefined }
|
||||
instance: { id: list[0].id, name: 'ok', extra: undefined },
|
||||
isNewInstance: true
|
||||
}));
|
||||
done();
|
||||
});
|
||||
|
@ -299,11 +310,14 @@ module.exports = function(dataSource, should) {
|
|||
function(err, record, created) {
|
||||
if (err) return done(err);
|
||||
record.id.should.eql(existingInstance.id);
|
||||
observedContexts.should.eql(aTestModelCtx({ instance: {
|
||||
id: getLastGeneratedUid(),
|
||||
name: existingInstance.name,
|
||||
extra: undefined
|
||||
}}));
|
||||
observedContexts.should.eql(aTestModelCtx({
|
||||
instance: {
|
||||
id: getLastGeneratedUid(),
|
||||
name: existingInstance.name,
|
||||
extra: undefined
|
||||
},
|
||||
isNewInstance: true
|
||||
}));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -317,11 +331,14 @@ module.exports = function(dataSource, should) {
|
|||
{ name: 'new-record' },
|
||||
function(err, record, created) {
|
||||
if (err) return done(err);
|
||||
observedContexts.should.eql(aTestModelCtx({ instance: {
|
||||
id: record.id,
|
||||
name: 'new-record',
|
||||
extra: undefined
|
||||
}}));
|
||||
observedContexts.should.eql(aTestModelCtx({
|
||||
instance: {
|
||||
id: record.id,
|
||||
name: 'new-record',
|
||||
extra: undefined
|
||||
},
|
||||
isNewInstance: true
|
||||
}));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -393,11 +410,14 @@ module.exports = function(dataSource, should) {
|
|||
{ name: 'new name' },
|
||||
function(err, instance) {
|
||||
if (err) return done(err);
|
||||
observedContexts.should.eql(aTestModelCtx({ instance: {
|
||||
id: instance.id,
|
||||
name: 'new name',
|
||||
extra: undefined
|
||||
}}));
|
||||
observedContexts.should.eql(aTestModelCtx({
|
||||
instance: {
|
||||
id: instance.id,
|
||||
name: 'new name',
|
||||
extra: undefined
|
||||
},
|
||||
isNewInstance: true
|
||||
}));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -492,17 +512,38 @@ module.exports = function(dataSource, should) {
|
|||
});
|
||||
});
|
||||
|
||||
it('triggers `after save` hook', function(done) {
|
||||
it('triggers `after save` hook on update', function(done) {
|
||||
TestModel.observe('after save', pushContextAndNext());
|
||||
|
||||
existingInstance.name = 'changed';
|
||||
existingInstance.save(function(err, instance) {
|
||||
if (err) return done(err);
|
||||
observedContexts.should.eql(aTestModelCtx({ instance: {
|
||||
id: existingInstance.id,
|
||||
name: 'changed',
|
||||
extra: undefined
|
||||
}}));
|
||||
observedContexts.should.eql(aTestModelCtx({
|
||||
instance: {
|
||||
id: existingInstance.id,
|
||||
name: 'changed',
|
||||
extra: undefined
|
||||
},
|
||||
isNewInstance: false
|
||||
}));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('triggers `after save` hook on create', function(done) {
|
||||
TestModel.observe('after save', pushContextAndNext());
|
||||
|
||||
var instance = new TestModel({ name: 'created' });
|
||||
instance.save(function(err, instance) {
|
||||
if (err) return done(err);
|
||||
observedContexts.should.eql(aTestModelCtx({
|
||||
instance: {
|
||||
id: instance.id,
|
||||
name: 'created',
|
||||
extra: undefined
|
||||
},
|
||||
isNewInstance: true
|
||||
}));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -597,11 +638,14 @@ module.exports = function(dataSource, should) {
|
|||
existingInstance.name = 'changed';
|
||||
existingInstance.updateAttributes({ name: 'changed' }, function(err) {
|
||||
if (err) return done(err);
|
||||
observedContexts.should.eql(aTestModelCtx({ instance: {
|
||||
id: existingInstance.id,
|
||||
name: 'changed',
|
||||
extra: undefined
|
||||
}}));
|
||||
observedContexts.should.eql(aTestModelCtx({
|
||||
instance: {
|
||||
id: existingInstance.id,
|
||||
name: 'changed',
|
||||
extra: undefined
|
||||
},
|
||||
isNewInstance: false
|
||||
}));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -781,7 +825,8 @@ module.exports = function(dataSource, should) {
|
|||
// The default unoptimized implementation runs
|
||||
// `instance.save` and thus a full instance is availalbe
|
||||
observedContexts.should.eql(aTestModelCtx({
|
||||
instance: { id: 'new-id', name: 'a name', extra: undefined }
|
||||
instance: { id: 'new-id', name: 'a name', extra: undefined },
|
||||
isNewInstance: true
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -859,11 +904,14 @@ module.exports = function(dataSource, should) {
|
|||
{ id: existingInstance.id, name: 'updated name' },
|
||||
function(err, instance) {
|
||||
if (err) return done(err);
|
||||
observedContexts.should.eql(aTestModelCtx({ instance: {
|
||||
id: existingInstance.id,
|
||||
name: 'updated name',
|
||||
extra: undefined
|
||||
}}));
|
||||
observedContexts.should.eql(aTestModelCtx({
|
||||
instance: {
|
||||
id: existingInstance.id,
|
||||
name: 'updated name',
|
||||
extra: undefined
|
||||
},
|
||||
isNewInstance: false
|
||||
}));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -875,11 +923,14 @@ module.exports = function(dataSource, should) {
|
|||
{ id: 'new-id', name: 'a name' },
|
||||
function(err, instance) {
|
||||
if (err) return done(err);
|
||||
observedContexts.should.eql(aTestModelCtx({ instance: {
|
||||
id: instance.id,
|
||||
name: 'a name',
|
||||
extra: undefined
|
||||
}}));
|
||||
observedContexts.should.eql(aTestModelCtx({
|
||||
instance: {
|
||||
id: instance.id,
|
||||
name: 'a name',
|
||||
extra: undefined
|
||||
},
|
||||
isNewInstance: true
|
||||
}));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -1126,12 +1177,12 @@ module.exports = function(dataSource, should) {
|
|||
existingInstance.delete(function(err) {
|
||||
if (err) return done(err);
|
||||
observedContexts.should.eql([
|
||||
aTestModelCtx({
|
||||
aTestModelCtx({
|
||||
hookState: { foo: 'bar', test: true },
|
||||
where: { id: '1' },
|
||||
instance: existingInstance
|
||||
}),
|
||||
aTestModelCtx({
|
||||
aTestModelCtx({
|
||||
hookState: { foo: 'BAR', test: true },
|
||||
where: { id: '1' },
|
||||
instance: existingInstance
|
||||
|
|
Loading…
Reference in New Issue