Permalink
Browse files

fixed; Model.update casts array vals correctly

  • Loading branch information...
1 parent 773f737 commit 4bc3547adafcc5fb4b206d714db9a01679055160 @aheckmann aheckmann committed Aug 29, 2011
Showing with 44 additions and 11 deletions.
  1. +2 −1 lib/document.js
  2. +20 −6 lib/schema.js
  3. +9 −1 lib/schema/array.js
  4. +12 −2 test/document.test.js
  5. +1 −1 test/model.test.js
View
@@ -287,9 +287,10 @@ Document.prototype.set = function (path, val, type) {
if (last) {
obj[parts[i]] = val;
} else {
- // TODO - does this handle obj[parts[i]] === 0 ?
if (obj[parts[i]] && obj[parts[i]].constructor === Object) {
obj = obj[parts[i]];
+ } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
+ obj = obj[parts[i]];
} else {
obj = obj[parts[i]] = {};
}
View
@@ -129,14 +129,28 @@ Schema.prototype.path = function (path, obj) {
// of an embedded document in an embedded array.
// In this case, we need to jump to the Array's
// schema and call path() from there to resolve to
- // the correct path type (otherwise, it falsely
- // resolves to undefined
- var self = this
- , subpaths = path.split(/\.\d+\.?/)
- .filter(Boolean); // removes empty strings
+ // the correct path type
+
+ var last
+ , self = this
+ , subpaths = path.split(/\.(\d+)\.?/)
+ .filter(Boolean) // removes empty strings
if (subpaths.length > 1) {
- return subpaths.reduce(function (val, subpath) {
+ last = subpaths.length - 1;
+ return subpaths.reduce(function (val, subpath, i) {
+ if (val && !val.schema) {
+ if (i === last && !/\D/.test(subpath) && val instanceof Types.Array) {
+ return val.caster; // StringSchema, NumberSchema, etc
+ } else {
+ return val;
+ }
+ }
+
+ if (!/\D/.test(subpath)) { // 'path.0.subpath' on path 0
+ return val;
+ }
+
return val ? val.schema.path(subpath)
: self.path(subpath);
}, null);
View
@@ -4,7 +4,7 @@
var SchemaType = require('../schematype')
, CastError = SchemaType.CastError
- , ArrayNumberSchema = function () {}
+ , NumberSchema = require('./number')
, Types = {
Boolean: require('./boolean')
, Date: require('./date')
@@ -179,6 +179,14 @@ SchemaArray.prototype.$conditionalHandlers = {
* @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' ||
View
@@ -32,6 +32,7 @@ TestDocument.prototype.__proto__ = Document.prototype;
var schema = TestDocument.prototype.schema = new Schema({
test : String
, oids : [ObjectId]
+ , numbers : [Number]
, nested : {
age : Number
, cool : ObjectId
@@ -515,7 +516,7 @@ module.exports = {
, obj = doc.toObject();
delete obj._id;
- obj.should.eql({ oids: [] });
+ obj.should.eql({ numbers: [], oids: [] });
},
// GH-209
@@ -559,6 +560,15 @@ module.exports = {
p.embed[0].test().should.equal('apple butter');
db.close();
- }
+ },
+ 'setting a positional path does not cast value to array': function () {
+ var doc = new TestDocument;
+ doc.init({ numbers: [1,3] });
+ doc.numbers[0].should.eql(1);
+ doc.numbers[1].valueOf().should.eql(3);
+ doc.set('numbers.1', 2);
+ doc.numbers[0].should.eql(1);
+ doc.numbers[1].valueOf().should.eql(2);
+ }
};
View
@@ -2685,7 +2685,7 @@ module.exports = {
db.close();
},
- 'test that we don\'t instantiate MongooseNumber in arrays': function () {
+ 'test that we instantiate MongooseNumber in arrays': function () {
var db = start()
, BlogPost = db.model('BlogPost', collection);

0 comments on commit 4bc3547

Please sign in to comment.