mongoose
Version:
Mongoose MongoDB ODM
200 lines (165 loc) • 4.13 kB
JavaScript
/*!
* Module dependencies.
*/
var Document = require('../document')
, inspect = require('util').inspect;
/**
* EmbeddedDocument constructor.
*
* @param {Object} obj js object returned from the db
* @param {MongooseDocumentArray} parentArr the parent array of this document
* @param {Boolean} skipId
* @inherits Document
* @api private
*/
function EmbeddedDocument (obj, parentArr, skipId) {
if (parentArr) {
this.__parentArray = parentArr;
this.__parent = parentArr._parent;
} else {
this.__parentArray = undefined;
this.__parent = undefined;
}
Document.call(this, obj, undefined, skipId);
var self = this;
this.on('isNew', function (val) {
self.isNew = val;
});
};
/*!
* Inherit from Document
*/
EmbeddedDocument.prototype.__proto__ = Document.prototype;
/**
* Marks the embedded doc modified.
*
* ####Example:
*
* var doc = blogpost.comments.id(hexstring);
* doc.mixed.type = 'changed';
* doc.markModified('mixed.type');
*
* @param {String} path the path which changed
* @api public
*/
EmbeddedDocument.prototype.markModified = function (path) {
if (!this.__parentArray) return;
this._activePaths.modify(path);
if (this.isNew) {
// Mark the WHOLE parent array as modified
// if this is a new document (i.e., we are initializing
// a document),
this.__parentArray._markModified();
} else
this.__parentArray._markModified(this, path);
};
/**
* Used as a stub for [hooks.js](https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3)
*
* ####NOTE:
*
* _This is a no-op. Does not actually save the doc to the db._
*
* @param {Function} [fn]
* @return {EmbeddedDocument} this
* @api private
*/
EmbeddedDocument.prototype.save = function(fn) {
if (fn)
fn(null);
return this;
};
/**
* Removes the subdocument from its parent array.
*
* @param {Function} [fn]
* @api public
*/
EmbeddedDocument.prototype.remove = function (fn) {
if (!this.__parentArray) return this;
var _id;
if (!this.willRemove) {
_id = this._doc._id;
if (!_id) {
throw new Error('For your own good, Mongoose does not know ' +
'how to remove an EmbeddedDocument that has no _id');
}
this.__parentArray.pull({ _id: _id });
this.willRemove = true;
}
if (fn)
fn(null);
return this;
};
/**
* Override #update method of parent documents.
* @api private
*/
EmbeddedDocument.prototype.update = function () {
throw new Error('The #update method is not available on EmbeddedDocuments');
}
/**
* Helper for console.log
*
* @api public
*/
EmbeddedDocument.prototype.inspect = function () {
return inspect(this.toObject());
};
/**
* Marks a path as invalid, causing validation to fail.
*
* @param {String} path the field to invalidate
* @param {String|Error} err error which states the reason `path` was invalid
* @return {Boolean}
* @api public
*/
EmbeddedDocument.prototype.invalidate = function (path, err, first) {
if (!this.__parent) return false;
var index = this.__parentArray.indexOf(this);
var parentPath = this.__parentArray._path;
var fullPath = [parentPath, index, path].join('.');
this.__parent.invalidate(fullPath, err);
if (first)
this._validationError = ownerDocument(this)._validationError;
return true;
}
/**
* Returns the top level document of this sub-document.
*
* @return {Document}
*/
EmbeddedDocument.prototype.ownerDocument = function () {
return ownerDocument(this);
}
/*!
* Returns the top level document of this sub-document.
*
* @return {Document}
*/
function ownerDocument (self) {
var parent = self.__parent;
while (parent.__parent)
parent = parent.__parent;
return parent;
}
/**
* Returns this sub-documents parent document.
*
* @api public
*/
EmbeddedDocument.prototype.parent = function () {
return this.__parent;
}
/**
* Returns this sub-documents parent array.
*
* @api public
*/
EmbeddedDocument.prototype.parentArray = function () {
return this.__parentArray;
}
/*!
* Module exports.
*/
module.exports = EmbeddedDocument;