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;
|
||||
}
|
||||
|
||||
var embeddedInstance = modelInstance[propertyName];
|
||||
var embeddedInstance = this.embeddedValue();
|
||||
|
||||
if (embeddedInstance) {
|
||||
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) {
|
||||
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) {
|
||||
|
@ -2186,6 +2233,8 @@ EmbedsOne.prototype.build = function(targetModelData) {
|
|||
var embeddedInstance = new modelTo(targetModelData);
|
||||
modelInstance[propertyName] = embeddedInstance;
|
||||
|
||||
this.prepareEmbeddedInstance(embeddedInstance);
|
||||
|
||||
return embeddedInstance;
|
||||
};
|
||||
|
||||
|
@ -2203,7 +2252,7 @@ EmbedsOne.prototype.update = function(targetModelData, options, cb) {
|
|||
var isInst = targetModelData instanceof ModelBaseClass;
|
||||
var data = isInst ? targetModelData.toObject() : targetModelData;
|
||||
|
||||
var embeddedInstance = modelInstance[propertyName];
|
||||
var embeddedInstance = this.embeddedValue();
|
||||
if (embeddedInstance instanceof modelTo) {
|
||||
cb = cb || utils.createPromiseCallback();
|
||||
var hookState = {};
|
||||
|
|
|
@ -3775,6 +3775,53 @@ describe('relations', function() {
|
|||
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() {
|
||||
|
|
Loading…
Reference in New Issue