mongoose
Version:
Mongoose MongoDB ODM
169 lines (141 loc) • 3.52 kB
JavaScript
/*!
* Module dependencies.
*/
var MongooseArray = require('./array')
, driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'
, ObjectId = require(driver + '/objectid')
, ObjectIdSchema = require('../schema/objectid')
, util = require('util')
/**
* DocumentArray constructor
*
* @param {Array} values
* @param {String} path the path to this array
* @param {Document} doc parent document
* @api private
* @return {MongooseDocumentArray}
* @inherits MongooseArray
* @see http://bit.ly/f6CnZU
*/
function MongooseDocumentArray (values, path, doc) {
var arr = [];
// Values always have to be passed to the constructor to initialize, since
// otherwise MongooseArray#push will mark the array as modified to the parent.
arr.push.apply(arr, values);
arr.__proto__ = MongooseDocumentArray.prototype;
arr._atomics = {};
arr.validators = [];
arr._path = path;
if (doc) {
arr._parent = doc;
arr._schema = doc.schema.path(path);
doc.on('save', arr.notify('save'));
doc.on('isNew', arr.notify('isNew'));
}
return arr;
};
/*!
* Inherits from MongooseArray
*/
MongooseDocumentArray.prototype.__proto__ = MongooseArray.prototype;
/**
* Overrides MongooseArray#cast
*
* @api private
*/
MongooseDocumentArray.prototype._cast = function (value) {
var doc = new this._schema.casterConstructor(value, this);
return doc;
};
/**
* Searches array items for the first document with a matching id.
*
* ####Example:
*
* var embeddedDoc = m.array.id(some_id);
*
* @return {EmbeddedDocument|null} the subdocuent or null if not found.
* @param {ObjectId|String|Number|Buffer} id
* @api public
*/
MongooseDocumentArray.prototype.id = function (id) {
var casted
, _id;
try {
casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));
} catch (e) {
casted = null;
}
for (var i = 0, l = this.length; i < l; i++) {
_id = this[i].get('_id');
if (!(_id instanceof ObjectId)) {
if (String(id) == _id)
return this[i];
} else {
if (casted == _id)
return this[i];
}
}
return null;
};
/**
* Returns a native js Array of plain js objects
*
* ####NOTE:
*
* _Each sub-document is converted to a plain object by calling its `#toObject` method._
*
* @return {Array}
* @api public
*/
MongooseDocumentArray.prototype.toObject = function () {
return this.map(function (doc) {
return doc && doc.toObject() || null;
});
};
/**
* Helper for console.log
*
* @api public
*/
MongooseDocumentArray.prototype.inspect = function () {
return '[' + this.map(function (doc) {
if (doc) {
return doc.inspect
? doc.inspect()
: util.inspect(doc)
}
return 'null'
}).join('\n') + ']';
};
/**
* Creates a subdocument casted to this schema.
*
* This is the same subdocument constructor used for casting.
*
* @param {Object} obj the value to cast to this arrays SubDocument schema
* @api public
*/
MongooseDocumentArray.prototype.create = function (obj) {
return new this._schema.casterConstructor(obj);
}
/**
* Creates a fn that notifies all child docs of `event`.
*
* @param {String} event
* @return {Function}
* @api private
*/
MongooseDocumentArray.prototype.notify = function notify (event) {
var self = this;
return function notify (val) {
var i = self.length;
while (i--) {
self[i].emit(event, val);
}
}
}
/*!
* Module exports.
*/
module.exports = MongooseDocumentArray;