diff options
| author | Jules Laplace <jules@okfoc.us> | 2012-09-24 16:22:07 -0400 |
|---|---|---|
| committer | Jules Laplace <jules@okfoc.us> | 2012-09-24 16:22:07 -0400 |
| commit | 686106d544ecc3b6ffd4db2b665d3bc879a58d8c (patch) | |
| tree | a5b5e50237cef70e12f0745371896e96f5f6d578 /node_modules/mongoose/lib/schema/array.js | |
ok
Diffstat (limited to 'node_modules/mongoose/lib/schema/array.js')
| -rw-r--r-- | node_modules/mongoose/lib/schema/array.js | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/node_modules/mongoose/lib/schema/array.js b/node_modules/mongoose/lib/schema/array.js new file mode 100644 index 0000000..6458a73 --- /dev/null +++ b/node_modules/mongoose/lib/schema/array.js @@ -0,0 +1,232 @@ +/** + * Module dependencies. + */ + +var SchemaType = require('../schematype') + , CastError = SchemaType.CastError + , NumberSchema = require('./number') + , Types = { + Boolean: require('./boolean') + , Date: require('./date') + , Number: ArrayNumberSchema + , String: require('./string') + , ObjectId: require('./objectid') + , Buffer: require('./buffer') + } + , MongooseArray = require('../types').Array + , Mixed = require('./mixed') + , Query = require('../query') + , isMongooseObject = require('../utils').isMongooseObject + +/** + * Array SchemaType constructor + * + * @param {String} key + * @param {SchemaType} cast + * @api private + */ + +function SchemaArray (key, cast, options) { + SchemaType.call(this, key, options); + + if (cast) { + var castOptions = {}; + + if ('Object' === cast.constructor.name) { + if (cast.type) { + // support { type: Woot } + castOptions = cast; + cast = cast.type; + delete castOptions.type; + } else { + cast = Mixed; + } + } + + var caster = cast.name in Types ? Types[cast.name] : cast; + this.casterConstructor = caster; + this.caster = new caster(null, castOptions); + } + + var self = this + , defaultArr + , fn; + + if (this.defaultValue) { + defaultArr = this.defaultValue; + fn = 'function' == typeof defaultArr; + } + + this.default(function(){ + var arr = fn ? defaultArr() : defaultArr || []; + return new MongooseArray(arr, self.path, this); + }); +}; + +/** + * Inherits from SchemaType. + */ + +SchemaArray.prototype.__proto__ = SchemaType.prototype; + +/** + * Check required + * + * @api private + */ + +SchemaArray.prototype.checkRequired = function (value) { + return !!(value && value.length); +}; + +/** + * Overrides the getters application for the population special-case + * TODO: implement this in SchemaObjectIdArray + * + * @param {Object} value + * @param {Object} scope + * @api private + */ + +SchemaArray.prototype.applyGetters = function (value, scope) { + if (this.caster.options && this.caster.options.ref) { + // means the object id was populated + return value; + } + + return SchemaType.prototype.applyGetters.call(this, value, scope); +}; + +/** + * Casts contents + * + * @param {Object} value + * @param {Document} document that triggers the casting + * @param {Boolean} whether this is an initialization cast + * @api private + */ + +SchemaArray.prototype.cast = function (value, doc, init) { + if (Array.isArray(value)) { + if (!(value instanceof MongooseArray)) { + value = new MongooseArray(value, this.path, doc); + } + + if (this.caster) { + try { + for (var i = 0, l = value.length; i < l; i++) { + value[i] = this.caster.cast(value[i], doc, init); + } + } catch (e) { + // rethrow + throw new CastError(e.type, value); + } + } + + return value; + } else { + return this.cast([value], doc, init); + } +}; + +SchemaArray.prototype.castForQuery = function ($conditional, val) { + var handler; + if (arguments.length === 2) { + handler = this.$conditionalHandlers[$conditional]; + if (!handler) + throw new Error("Can't use " + $conditional + " with Array."); + val = handler.call(this, val); + } else { + val = $conditional; + var proto = this.casterConstructor.prototype; + var method = proto.castForQuery || proto.cast; + if (Array.isArray(val)) { + val = val.map(function (v) { + if (method) v = method.call(proto, v); + return isMongooseObject(v) + ? v.toObject() + : v; + }); + } else if (method) { + val = method.call(proto, val); + } + } + return val && isMongooseObject(val) + ? val.toObject() + : val; +}; + +SchemaArray.prototype.$conditionalHandlers = { + '$all': function handle$all (val) { + if (!Array.isArray(val)) { + val = [val]; + } + + val = val.map(function (v) { + if (v && 'Object' === v.constructor.name) { + var o = {}; + o[this.path] = v; + var query = new Query(o); + query.cast(this.casterConstructor); + return query._conditions[this.path]; + } + return v; + }, this); + + return this.castForQuery(val); + } + , '$elemMatch': function (val) { + var query = new Query(val); + query.cast(this.casterConstructor); + return query._conditions; + } + , '$size': function (val) { + return ArrayNumberSchema.prototype.cast.call(this, val); + } + , '$ne': SchemaArray.prototype.castForQuery + , '$in': SchemaArray.prototype.castForQuery + , '$nin': SchemaArray.prototype.castForQuery + , '$regex': SchemaArray.prototype.castForQuery + , '$near': SchemaArray.prototype.castForQuery + , '$nearSphere': SchemaArray.prototype.castForQuery + , '$within': function(val) { + var query = new Query(val); + query.cast(this.casterConstructor) + return query._conditions; + } + , '$maxDistance': function (val) { + return ArrayNumberSchema.prototype.cast.call(this, val); + } +}; + +/** + * Number casting for arrays (equivalent, but without MongoseNumber) + * + * @see GH-176 + * @param {Object} value + * @api private + */ + +// subclass number schema to override casting +// to disallow non-numbers being saved +function ArrayNumberSchema (key, options) { + NumberSchema.call(this, key, options); +} + +ArrayNumberSchema.prototype.__proto__ = NumberSchema.prototype; + +ArrayNumberSchema.prototype.cast = function (value) { + if (!isNaN(value)) { + if (value instanceof Number || typeof value == 'number' || + (value.toString && value.toString() == Number(value))) + return Number(value); + } + + throw new CastError('number', value); +}; + +/** + * Module exports. + */ + +module.exports = SchemaArray; |
