UNPKG

mongoose

Version:

Mongoose MongoDB ODM

169 lines (141 loc) 3.52 kB
/*! * 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;