Skip to content

Commit

Permalink
strict mode now enabled by default
Browse files Browse the repository at this point in the history
turn it back off with new Schema({..}, { strict: false })

closes Automattic#952
  • Loading branch information
aheckmann committed Jun 13, 2012
1 parent 7e758b6 commit a4dd9de
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 60 deletions.
2 changes: 1 addition & 1 deletion lib/model.js
Expand Up @@ -1243,7 +1243,7 @@ Model.mapReduce = function mapReduce (o, callback) {
var self = this;

if (!Model.mapReduce.schema) {
var opts = { noId: true, noVirtualId: true }
var opts = { noId: true, noVirtualId: true, strict: false }
Model.mapReduce.schema = new Schema({}, opts);
}

Expand Down
80 changes: 44 additions & 36 deletions lib/schema.js
Expand Up @@ -32,7 +32,7 @@ function Schema (obj, options) {
// set options
this.options = utils.options({
safe: true
, strict: false
, strict: true
, capped: false // { size, max, autoIndexId }
, versionKey: '__v'
}, options);
Expand Down Expand Up @@ -143,39 +143,10 @@ Schema.prototype.path = function (path, obj) {
if (this.paths[path]) return this.paths[path];
if (this.subpaths[path]) return this.subpaths[path];

// Sometimes path will come in as
// pathNameA.4.pathNameB where 4 means the index
// 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

var last
, self = this
, subpaths = path.split(/\.(\d+)\.?/)
.filter(Boolean) // removes empty strings

if (subpaths.length > 1) {
last = subpaths.length - 1;
return this.subpaths[path] = 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);
}

return this.paths[subpaths[0]];
// subpaths?
return /\.\d+\.?/.test(path)
? getPositionalPath(this, path)
: undefined;
}

// update the tree
Expand All @@ -195,7 +166,7 @@ Schema.prototype.path = function (path, obj) {
};

/**
* Converts -- e.g., Number, [SomeSchema],
* Converts -- e.g., Number, [SomeSchema],
* { type: String, enum: ['m', 'f'] } -- into
* the appropriate Mongoose Type, which we use
* later for casting, validation, etc.
Expand Down Expand Up @@ -309,9 +280,46 @@ Schema.prototype.pathType = function (path) {
if (path in this.paths) return 'real';
if (path in this.virtuals) return 'virtual';
if (path in this.nested) return 'nested';
return 'adhocOrUndefined';
if (path in this.subpaths) return 'real';

if (/\.\d+\.?/.test(path) && getPositionalPath(this, path)) {
return 'real';
} else {
return 'adhocOrUndefined'
}
};

function getPositionalPath (self, path) {
var subpaths = path.split(/\.(\d+)\.?/).filter(Boolean);
if (subpaths.length < 2) {
return self.paths[subpaths[0]];
}

var val = self.path(subpaths[0])
, last = subpaths.length - 1
, subpath;

for (var i = 1; i < subpaths.length; ++i) {
var subpath = subpaths[i];

if (i === last &&
val &&
!val.schema &&
!/\D/.test(subpath) &&
val instanceof Types.Array) {
// StringSchema, NumberSchema, etc
val = val.caster;
continue;
}

// 'path.0.subpath'
if (!/\D/.test(subpath)) continue;
val = val.schema.path(subpath);
}

return self.subpaths[path] = val;
}

/**
* Adds a method call to the queue
*
Expand Down
18 changes: 9 additions & 9 deletions test/document.strict.test.js
Expand Up @@ -29,12 +29,12 @@ module.exports = {
var lax = new Schema({
ts : { type: Date, default: Date.now }
, content: String
});
}, { strict: false });

var strict = new Schema({
ts : { type: Date, default: Date.now }
, content: String
}, { strict: true });
});

var Lax = db.model('Lax', lax);
var Strict = db.model('Strict', strict);
Expand Down Expand Up @@ -93,11 +93,11 @@ module.exports = {

var lax = new Schema({
name: { last: String }
});
}, { strict: false });

var strict = new Schema({
name: { last: String }
}, { strict: true });
});

var Lax = db.model('NestedLax', lax, 'nestdoc'+random());
var Strict = db.model('NestedStrict', strict, 'nestdoc'+random());
Expand Down Expand Up @@ -133,15 +133,15 @@ module.exports = {
var lax = new Schema({
ts : { type: Date, default: Date.now }
, content: String
});
}, { strict: false });

var strict = new Schema({
ts : { type: Date, default: Date.now }
, content: String
}, { strict: true });
});

var Lax = db.model('EmbeddedLax', new Schema({ dox: [lax] }), 'embdoc'+random());
var Strict = db.model('EmbeddedStrict', new Schema({ dox: [strict] }), 'embdoc'+random());
var Lax = db.model('EmbeddedLax', new Schema({ dox: [lax] }, { strict: false }), 'embdoc'+random());
var Strict = db.model('EmbeddedStrict', new Schema({ dox: [strict] }, { strict: false }), 'embdoc'+random());

var l = new Lax({ dox: [{content: 'sample', rouge: 'data'}] });
l.dox[0]._strictMode.should.be.false;
Expand Down Expand Up @@ -184,7 +184,7 @@ module.exports = {
var strictSchema = new Schema({
email: String
, prop: String
}, {strict: true});
});

strictSchema
.virtual('myvirtual')
Expand Down
4 changes: 2 additions & 2 deletions test/model.mapreduce.test.js
Expand Up @@ -129,12 +129,12 @@ module.exports = {
assert.equal('nathan', docs[3]._id);

// update casting works
ret.findOneAndUpdate({ _id: 'aaron' }, { updated: true }, function (err, doc) {
ret.findOneAndUpdate({ _id: 'aaron' }, { published: true }, function (err, doc) {
db.close();
if (err) throw err;
assert.ok(doc);
assert.equal('aaron', doc._id);
assert.equal(true, doc.updated);
assert.equal(true, doc.published);
});
});
});
Expand Down
3 changes: 2 additions & 1 deletion test/model.querying.test.js
Expand Up @@ -52,7 +52,8 @@ mongoose.model('BlogPostB', BlogPostB);
var collection = 'blogposts_' + random();

var ModSchema = new Schema({
num: Number
num: Number
, str: String
});
mongoose.model('Mod', ModSchema);

Expand Down
4 changes: 2 additions & 2 deletions test/model.test.js
Expand Up @@ -3592,7 +3592,7 @@ module.exports = {

var t = new T({ nest: null });

should.strictEqual(t.nest.st, null);
should.strictEqual(t.nest.st, undefined);
t.nest = { st: "jsconf rules" };
t.nest.toObject().should.eql({ st: "jsconf rules" });
t.nest.st.should.eql("jsconf rules");
Expand Down Expand Up @@ -4322,7 +4322,7 @@ module.exports = {

InvalidateSchema = new Schema({
prop: { type: String },
});
}, { strict: false });

mongoose.model('InvalidateSchema', InvalidateSchema);

Expand Down
12 changes: 6 additions & 6 deletions test/model.update.test.js
Expand Up @@ -47,7 +47,7 @@ var BlogPost = new Schema({
, numbers : [Number]
, owners : [ObjectId]
, comments : [Comments]
});
}, { strict: false });

BlogPost.virtual('titleWithAuthor')
.get(function () {
Expand All @@ -67,11 +67,11 @@ BlogPost.static('woot', function(){
return this;
});

mongoose.model('BlogPost', BlogPost);
mongoose.model('BlogPostForUpdates', BlogPost);

var collection = 'blogposts_' + random();

var strictSchema = new Schema({ name: String, x: { nested: String }}, { strict: true });
var strictSchema = new Schema({ name: String, x: { nested: String }});
strictSchema.virtual('foo').get(function () {
return 'i am a virtual FOO!'
});
Expand All @@ -81,7 +81,7 @@ module.exports = {

'test updating documents': function () {
var db = start()
, BlogPost = db.model('BlogPost', collection)
, BlogPost = db.model('BlogPostForUpdates', collection)
, title = 'Tobi ' + random()
, author = 'Brian ' + random()
, newTitle = 'Woot ' + random()
Expand Down Expand Up @@ -493,7 +493,7 @@ module.exports = {

'test updating numbers atomically': function () {
var db = start()
, BlogPost = db.model('BlogPost', collection)
, BlogPost = db.model('BlogPostForUpdates', collection)
, totalDocs = 4
, saveQueue = [];

Expand Down Expand Up @@ -555,7 +555,7 @@ module.exports = {

'model.update passes number of affected documents': function () {
var db = start()
, B = db.model('BlogPost', 'wwwwowowo'+random())
, B = db.model('BlogPostForUpdates', 'wwwwowowo'+random())

B.create({ title: 'one'},{title:'two'},{title:'three'}, function (err) {
should.strictEqual(null, err);
Expand Down
2 changes: 1 addition & 1 deletion test/schema.onthefly.test.js
Expand Up @@ -11,7 +11,7 @@ var start = require('./common')

var DecoratedSchema = new Schema({
title : String
});
}, { strict: false });

mongoose.model('Decorated', DecoratedSchema);

Expand Down
4 changes: 2 additions & 2 deletions test/versioning.test.js
Expand Up @@ -111,7 +111,7 @@ module.exports = {
function test3 (err, a, b) {
assert.ifError(err);
assert.equal(a.meta.numbers.length, 5);
assert.equal(a.meta.numbers.length, 5);
assert.equal(b.meta.numbers.length, 5);
assert.equal(-1, a.meta.numbers.indexOf(10));
assert.ok(~a.meta.numbers.indexOf(20));

Expand All @@ -123,7 +123,7 @@ module.exports = {
}

function test4 (err, a, b) {
assert.ok(/No matching document/.test(err));
assert.ok(/No matching document/.test(err), err);
a.set('arr.0.0', 'updated');
var d = a._delta()[0];
assert.equal(a._doc.__v, d.__v, 'version should be added to where clause')
Expand Down

0 comments on commit a4dd9de

Please sign in to comment.