Persist changes on parent for embedsOne
Allow direct save of changes on embedded model to be persisted on parent document. Person.embedsOne(Address); Person.findById(someId) .then(function(p){ var address = p.addressItem(); address.street = 'new street' // This will now persist changes on parent document return address.save(); })
This commit is contained in:
parent
baef033115
commit
af8cf19242
|
@ -2068,7 +2068,7 @@ EmbedsOne.prototype.related = function(condOrRefresh, options, cb) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var embeddedInstance = modelInstance[propertyName];
|
var embeddedInstance = this.embeddedValue();
|
||||||
|
|
||||||
if (embeddedInstance) {
|
if (embeddedInstance) {
|
||||||
embeddedInstance.__persisted = true;
|
embeddedInstance.__persisted = true;
|
||||||
|
@ -2083,9 +2083,56 @@ EmbedsOne.prototype.related = function(condOrRefresh, options, cb) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EmbedsOne.prototype.prepareEmbeddedInstance = function(inst) {
|
||||||
|
if (inst && inst.triggerParent !== 'function') {
|
||||||
|
var self = this;
|
||||||
|
var propertyName = this.definition.keyFrom;
|
||||||
|
var modelInstance = this.modelInstance;
|
||||||
|
if (this.definition.options.persistent) {
|
||||||
|
var pk = this.definition.keyTo;
|
||||||
|
inst.__persisted = !!inst[pk];
|
||||||
|
} else {
|
||||||
|
inst.__persisted = true;
|
||||||
|
}
|
||||||
|
inst.triggerParent = function(actionName, callback) {
|
||||||
|
if (actionName === 'save') {
|
||||||
|
var embeddedValue = self.embeddedValue();
|
||||||
|
modelInstance.updateAttribute(propertyName,
|
||||||
|
embeddedValue, function(err, modelInst) {
|
||||||
|
callback(err, err ? null : modelInst);
|
||||||
|
});
|
||||||
|
} else if (actionName === 'destroy') {
|
||||||
|
modelInstance.unsetAttribute(propertyName, true);
|
||||||
|
// cannot delete property completely the way save works. operator $unset needed like mongo
|
||||||
|
modelInstance.save(function(err, modelInst) {
|
||||||
|
callback(err, modelInst);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
process.nextTick(callback);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var originalTrigger = inst.trigger;
|
||||||
|
inst.trigger = function(actionName, work, data, callback) {
|
||||||
|
if (typeof work === 'function') {
|
||||||
|
var originalWork = work;
|
||||||
|
work = function(next) {
|
||||||
|
originalWork.call(this, function(done) {
|
||||||
|
inst.triggerParent(actionName, function(err, inst) {
|
||||||
|
next(done); // TODO [fabien] - error handling?
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
originalTrigger.call(this, actionName, work, data, callback);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
EmbedsOne.prototype.embeddedValue = function(modelInstance) {
|
EmbedsOne.prototype.embeddedValue = function(modelInstance) {
|
||||||
modelInstance = modelInstance || this.modelInstance;
|
modelInstance = modelInstance || this.modelInstance;
|
||||||
return modelInstance[this.definition.keyFrom];
|
var embeddedValue = modelInstance[this.definition.keyFrom];
|
||||||
|
this.prepareEmbeddedInstance(embeddedValue);
|
||||||
|
return embeddedValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
EmbedsOne.prototype.create = function(targetModelData, options, cb) {
|
EmbedsOne.prototype.create = function(targetModelData, options, cb) {
|
||||||
|
@ -2186,6 +2233,8 @@ EmbedsOne.prototype.build = function(targetModelData) {
|
||||||
var embeddedInstance = new modelTo(targetModelData);
|
var embeddedInstance = new modelTo(targetModelData);
|
||||||
modelInstance[propertyName] = embeddedInstance;
|
modelInstance[propertyName] = embeddedInstance;
|
||||||
|
|
||||||
|
this.prepareEmbeddedInstance(embeddedInstance);
|
||||||
|
|
||||||
return embeddedInstance;
|
return embeddedInstance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2203,7 +2252,7 @@ EmbedsOne.prototype.update = function(targetModelData, options, cb) {
|
||||||
var isInst = targetModelData instanceof ModelBaseClass;
|
var isInst = targetModelData instanceof ModelBaseClass;
|
||||||
var data = isInst ? targetModelData.toObject() : targetModelData;
|
var data = isInst ? targetModelData.toObject() : targetModelData;
|
||||||
|
|
||||||
var embeddedInstance = modelInstance[propertyName];
|
var embeddedInstance = this.embeddedValue();
|
||||||
if (embeddedInstance instanceof modelTo) {
|
if (embeddedInstance instanceof modelTo) {
|
||||||
cb = cb || utils.createPromiseCallback();
|
cb = cb || utils.createPromiseCallback();
|
||||||
var hookState = {};
|
var hookState = {};
|
||||||
|
|
|
@ -3775,6 +3775,53 @@ describe('relations', function() {
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should also save changes when directly saving the embedded model', function(done) {
|
||||||
|
// Passport should normally have an id for the direct save to work. For now override the check
|
||||||
|
var originalHasPK = Passport.definition.hasPK;
|
||||||
|
Passport.definition.hasPK = function() { return true; };
|
||||||
|
Person.findById(personId)
|
||||||
|
.then(function(p) {
|
||||||
|
return p.passportItem.create({ name: 'Mitsos' });
|
||||||
|
})
|
||||||
|
.then(function(passport) {
|
||||||
|
passport.name = 'Jim';
|
||||||
|
return passport.save();
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
return Person.findById(personId);
|
||||||
|
})
|
||||||
|
.then(function(person) {
|
||||||
|
person.passportItem().toObject().should.eql({ name: 'Jim' });
|
||||||
|
// restore original hasPk
|
||||||
|
Passport.definition.hasPK = originalHasPK;
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
Passport.definition.hasPK = originalHasPK;
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should delete the embedded document and also update parent', function(done) {
|
||||||
|
var originalHasPK = Passport.definition.hasPK;
|
||||||
|
Passport.definition.hasPK = function() { return true; };
|
||||||
|
Person.findById(personId)
|
||||||
|
.then(function(p) {
|
||||||
|
return p.passportItem().destroy();
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
return Person.findById(personId);
|
||||||
|
})
|
||||||
|
.then(function(person) {
|
||||||
|
person.should.have.property('passport', null);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
Passport.definition.hasPK = originalHasPK;
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('embedsOne - persisted model', function() {
|
describe('embedsOne - persisted model', function() {
|
||||||
|
|
Loading…
Reference in New Issue