Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 126 additions & 44 deletions lib/relation-definition.js
Original file line number Diff line number Diff line change
Expand Up @@ -1856,27 +1856,35 @@ EmbedsOne.prototype.create = function (targetModelData, cb) {

var inst = this.callScopeMethod('build', targetModelData);

var updateEmbedded = function() {
var updateEmbedded = function(callback) {
modelInstance.updateAttribute(propertyName,
inst, function(err) {
cb(err, err ? null : inst);
callback(err, err ? null : inst);
});
};

if (this.definition.options.persistent) {
inst.save(function(err) { // will validate
if (err) return cb(err, inst);
updateEmbedded();
updateEmbedded(cb);
});
} else {
var err = inst.isValid() ? null : new ValidationError(inst);
if (err) {
process.nextTick(function() {
cb(err);
});
} else {
updateEmbedded();
}
var context = { Model: modelTo, instance: inst, hookState: {} };
modelTo.notifyObserversOf('before save', context, function(err) {
err = err || (inst.isValid() ? null : new ValidationError(inst));
if (err) {
process.nextTick(function() {
cb(err);
});
} else {
updateEmbedded(function(err, inst) {
if (err) return cb(err, null);
modelTo.notifyObserversOf('after save', context, function(err) {
cb(err, err ? null : inst);
});
});
}
});
}
};

Expand Down Expand Up @@ -1916,14 +1924,40 @@ EmbedsOne.prototype.update = function (targetModelData, cb) {

var isInst = targetModelData instanceof ModelBaseClass;
var data = isInst ? targetModelData.toObject() : targetModelData;
data = typeof data === 'object' ? data : {};

var embeddedInstance = modelInstance[propertyName];
if (embeddedInstance instanceof modelTo) {
embeddedInstance.setAttributes(data);
if (typeof cb === 'function') {
modelInstance.save(function(err, inst) {
cb(err, inst ? inst[propertyName] : embeddedInstance);
var hookState = {};
var context = {
Model: modelTo,
currentInstance: embeddedInstance,
data: data,
hookState: hookState
};
modelTo.notifyObserversOf('before save', context, function(err) {
if (err) return cb(err);

embeddedInstance.setAttributes(data);

var err = embeddedInstance.isValid() ? null : new ValidationError(embeddedInstance);
if (err && typeof cb === 'function') {
return process.nextTick(function() {
cb(err, embeddedInstance);
});
}

modelInstance.save(function(err, inst) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated bug: the modelTo instance should be validated before save, similarly as EmbedsOne.prototype.create does.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I think that call is obsolete in EmbedsOne.prototype.create - a custom validation has been setup to handle this from the parent model. I prefer to remove it and let that validation handle it. I'll investigate.

if (err) return cb(err);
context = { Model: modelTo, instance: embeddedInstance, hookState: hookState };
modelTo.notifyObserversOf('after save', context, function(err) {
cb(err, inst ? inst[propertyName] : embeddedInstance);
});
});
});
} else {
embeddedInstance.setAttributes(data);
}
} else if (!embeddedInstance && cb) {
this.callScopeMethod('create', data, cb);
Expand All @@ -1933,11 +1967,23 @@ EmbedsOne.prototype.update = function (targetModelData, cb) {
};

EmbedsOne.prototype.destroy = function (cb) {
var modelTo = this.definition.modelTo;
var modelInstance = this.modelInstance;
var propertyName = this.definition.keyFrom;
var embeddedInstance = modelInstance[propertyName];

if (!embeddedInstance) return cb && cb(null, 0);

modelInstance.unsetAttribute(propertyName, true);
modelInstance.save(function (err, result) {
cb && cb(err, result);

var context = { Model: modelTo, instance: embeddedInstance, hookState: {} };
modelTo.notifyObserversOf('before delete', context, function(err) {
if (err) return cb && cb(err);
modelInstance.save(function(err, result) {
modelTo.notifyObserversOf('after delete', context, function(err) {
cb && cb(err, result);
});
});
});
};

Expand Down Expand Up @@ -2223,24 +2269,42 @@ EmbedsMany.prototype.updateById = function (fkId, data, cb) {
var embeddedList = this.embeddedList();

var inst = this.findById(fkId);
var data = typeof data === 'object' ? data : {};

if (inst instanceof modelTo) {
if (typeof data === 'object') {
inst.setAttributes(data);
}
var err = inst.isValid() ? null : new ValidationError(inst);
if (err && typeof cb === 'function') {
return process.nextTick(function() {
cb(err, inst);
});
}
var hookState = {};
var context = {
Model: modelTo,
currentInstance: inst,
data: data,
hookState: hookState
};
modelTo.notifyObserversOf('before save', context, function(err) {
if (err) return cb && cb(err);

if (typeof cb === 'function') {
modelInstance.updateAttribute(propertyName,
embeddedList, function(err) {
cb(err, inst);
});
}
inst.setAttributes(data);

var err = inst.isValid() ? null : new ValidationError(inst);
if (err && typeof cb === 'function') {
return process.nextTick(function() {
cb(err, inst);
});
}

context = { Model: modelTo, instance: inst, hookState: hookState };

if (typeof cb === 'function') {
modelInstance.updateAttribute(propertyName,
embeddedList, function(err) {
if (err) return cb(err, inst);
modelTo.notifyObserversOf('after save', context, function(err) {
cb(err, inst);
});
});
} else {
modelTo.notifyObserversOf('after save', context);
}
});
} else if (typeof cb === 'function') {
process.nextTick(function() {
cb(null, null); // not found
Expand All @@ -2259,15 +2323,23 @@ EmbedsMany.prototype.destroyById = function (fkId, cb) {
var inst = (fkId instanceof modelTo) ? fkId : this.findById(fkId);

if (inst instanceof modelTo) {
var index = embeddedList.indexOf(inst);
if (index > -1) embeddedList.splice(index, 1);
if (typeof cb === 'function') {
modelInstance.updateAttribute(propertyName,
embeddedList, function(err) {
cb(err);
modelTo.emit('deleted', inst.id, inst.toJSON());
});
}
var context = { Model: modelTo, instance: inst, hookState: {} };
modelTo.notifyObserversOf('before delete', context, function(err) {
var index = embeddedList.indexOf(inst);
if (index > -1) embeddedList.splice(index, 1);
if (typeof cb === 'function') {
modelInstance.updateAttribute(propertyName,
embeddedList, function(err) {
if (err) return cb(err);
modelTo.notifyObserversOf('after delete', context, function(err) {
cb(err);
if (!err) modelTo.emit('deleted', inst.id, inst.toJSON());
});
});
} else {
modelTo.notifyObserversOf('after delete', context);
}
});
} else if (typeof cb === 'function') {
process.nextTick(cb); // not found
}
Expand Down Expand Up @@ -2312,17 +2384,17 @@ EmbedsMany.prototype.create = function (targetModelData, cb) {

var inst = this.callScopeMethod('build', targetModelData);

var updateEmbedded = function() {
var updateEmbedded = function(callback) {
modelInstance.updateAttribute(propertyName,
embeddedList, function(err, modelInst) {
cb(err, err ? null : inst);
callback(err, err ? null : inst);
});
};

if (this.definition.options.persistent) {
inst.save(function(err) { // will validate
if (err) return cb(err, inst);
updateEmbedded();
updateEmbedded(cb);
});
} else {
var err = inst.isValid() ? null : new ValidationError(inst);
Expand All @@ -2331,9 +2403,19 @@ EmbedsMany.prototype.create = function (targetModelData, cb) {
cb(err);
});
} else {
updateEmbedded();
var context = { Model: modelTo, instance: inst, hookState: {} };
modelTo.notifyObserversOf('before save', context, function(err) {
if (err) return cb(err);
updateEmbedded(function(err, inst) {
if (err) return cb(err, null);
modelTo.notifyObserversOf('after save', context, function(err) {
cb(err, err ? null : inst);
});
});
});
}
}

};

EmbedsMany.prototype.build = function(targetModelData) {
Expand Down
Loading