Skip to content

Commit

Permalink
fixed; depopulation of mixed documents
Browse files Browse the repository at this point in the history
closes #1471
  • Loading branch information
aheckmann committed May 1, 2013
1 parent fb5d602 commit 66e2224
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 20 deletions.
10 changes: 3 additions & 7 deletions lib/document.js
Expand Up @@ -1427,12 +1427,9 @@ Document.prototype.$__doQueue = function () {
*/

Document.prototype.toObject = function (options) {
if (options && options.depopulate && !options.isParent) {
// populated paths that we set to a document?
Embedded || (Embedded = require('./types/embedded'));
if (!(this instanceof Embedded)) {
return clone(this._id, options);
}
if (options && options.depopulate && this.$__.wasPopulated) {
// populated paths that we set to a document
return clone(this._id, options);
}

// When internally saving this document we always pass options,
Expand All @@ -1444,7 +1441,6 @@ Document.prototype.toObject = function (options) {
}

;('minimize' in options) || (options.minimize = this.schema.options.minimize);
options.isParent = false;

var ret = clone(this._doc, options);

Expand Down
5 changes: 3 additions & 2 deletions lib/internal.js
Expand Up @@ -19,8 +19,9 @@ function InternalCache () {
this.version = undefined;
this.getters = {};
this._id = undefined;
this.populate = undefined;
this.populated = undefined;
this.populate = undefined; // what we want to populate in this doc
this.populated = undefined;// the _ids that have been populated
this.wasPopulated = false; // if this doc was the result of a population
this.scope = undefined;
this.activePaths = new ActiveRoster;

Expand Down
6 changes: 5 additions & 1 deletion lib/model.js
Expand Up @@ -170,7 +170,7 @@ Model.prototype.save = function save (fn) {

if (this.isNew) {
// send entire doc
var obj = this.toObject({ depopulate: 1, isParent: 1 });
var obj = this.toObject({ depopulate: 1 });
this.$__version(true, obj);
this.collection.insert(obj, options, complete);
this.$__reset();
Expand Down Expand Up @@ -1867,6 +1867,7 @@ function populate (model, docs, options, cb) {
Model.find(match, select, options.options, function (err, vals) {
if (err) return cb(err);

var lean = options.options && options.options.lean;
var len = vals.length;
var rawOrder = {};
var rawDocs = {}
Expand All @@ -1881,6 +1882,9 @@ function populate (model, docs, options, cb) {
key = String(utils.getValue('_id', val));
rawDocs[key] = val;
rawOrder[key] = i;

// flag each as result of population
if (!lean) val.$__.wasPopulated = true;
}

assignVals({
Expand Down
8 changes: 7 additions & 1 deletion lib/schema/buffer.js
Expand Up @@ -56,10 +56,15 @@ SchemaBuffer.prototype.cast = function (value, doc, init) {
if (SchemaType._isRef(this, value, doc, init)) {
// wait! we may need to cast this to a document

if (null == value) {
return value;
}

// lazy load
Document || (Document = require('./../document'));

if (value instanceof Document || null == value) {
if (value instanceof Document) {
value.$__.wasPopulated = true;
return value;
}

Expand All @@ -77,6 +82,7 @@ SchemaBuffer.prototype.cast = function (value, doc, init) {
var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
var pop = owner.populated(path, true);
var ret = new pop.options.model(value);
ret.$__.wasPopulated = true;
return ret;
}

Expand Down
11 changes: 9 additions & 2 deletions lib/schema/number.js
Expand Up @@ -115,10 +115,15 @@ SchemaNumber.prototype.cast = function (value, doc, init) {
if (SchemaType._isRef(this, value, doc, init)) {
// wait! we may need to cast this to a document

if (null == value) {
return value;
}

// lazy load
Document || (Document = require('./../document'));

if (value instanceof Document || null == value) {
if (value instanceof Document) {
value.$__.wasPopulated = true;
return value;
}

Expand All @@ -135,7 +140,9 @@ SchemaNumber.prototype.cast = function (value, doc, init) {
var path = doc.$__fullPath(this.path);
var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
var pop = owner.populated(path, true);
return new pop.options.model(value);
var ret = new pop.options.model(value);
ret.$__.wasPopulated = true;
return ret;
}

var val = value && value._id
Expand Down
11 changes: 9 additions & 2 deletions lib/schema/objectid.js
Expand Up @@ -55,10 +55,15 @@ ObjectId.prototype.cast = function (value, doc, init) {
if (SchemaType._isRef(this, value, doc, init)) {
// wait! we may need to cast this to a document

if (null == value) {
return value;
}

// lazy load
Document || (Document = require('./../document'));

if (value instanceof Document || null == value) {
if (value instanceof Document) {
value.$__.wasPopulated = true;
return value;
}

Expand All @@ -75,7 +80,9 @@ ObjectId.prototype.cast = function (value, doc, init) {
var path = doc.$__fullPath(this.path);
var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
var pop = owner.populated(path, true);
return new pop.options.model(value);
var ret = new pop.options.model(value);
ret.$__.wasPopulated = true;
return ret;
}

if (value === null) return value;
Expand Down
11 changes: 9 additions & 2 deletions lib/schema/string.js
Expand Up @@ -197,10 +197,15 @@ SchemaString.prototype.cast = function (value, doc, init) {
if (SchemaType._isRef(this, value, doc, init)) {
// wait! we may need to cast this to a document

if (null == value) {
return value;
}

// lazy load
Document || (Document = require('./../document'));

if (value instanceof Document || null == value) {
if (value instanceof Document) {
value.$__.wasPopulated = true;
return value;
}

Expand All @@ -217,7 +222,9 @@ SchemaString.prototype.cast = function (value, doc, init) {
var path = doc.$__fullPath(this.path);
var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
var pop = owner.populated(path, true);
return new pop.options.model(value);
var ret = new pop.options.model(value);
ret.$__.wasPopulated = true;
return ret;
}

if (value === null) {
Expand Down
5 changes: 2 additions & 3 deletions lib/types/array.js
Expand Up @@ -634,14 +634,13 @@ MongooseArray.prototype.set = function set (i, val) {
MongooseArray.prototype.toObject = function (options) {
if (options && options.depopulate) {
return this.map(function (doc) {
// this is called on populated arrays too
return doc instanceof Document
? doc._id
? doc.toObject(options)
: doc
});
}

return this.slice()
return this.slice();
}

/**
Expand Down
58 changes: 58 additions & 0 deletions test/model.populate.test.js
Expand Up @@ -2298,4 +2298,62 @@ describe('model: populate:', function(){
});
});
})

describe('leaves Documents within Mixed properties alone (gh-1471)', function(){
var db;
var Cat;
var Litter;

before(function(){
db = start();
Cat = db.model('cats', new Schema({ name: String }));
var litterSchema = new Schema({name: String, cats: {}, o: {}, a: []});
Litter = db.model('litters', litterSchema);
});

after(function(done){
db.close(done);
});

it('when saving new docs', function(done){
Cat.create({name:'new1'},{name:'new2'},{name:'new3'}, function (err, a, b, c) {
if (err) return done(err);

Litter.create({
name: 'new'
, cats:[a]
, o: b
, a: [c]
}, confirm(done));
})
})

it('when saving existing docs 5T5', function(done){
Cat.create({name:'ex1'},{name:'ex2'},{name:'ex3'}, function (err, a, b, c) {
if (err) return done(err);

Litter.create({name:'existing'}, function (err, doc) {
doc.cats = [a];
doc.o = b;
doc.a = [c]
doc.save(confirm(done));
});
});
})

function confirm (done) {
return function (err, litter) {
if (err) return done(err);
Litter.findById(litter).lean().exec(function (err, doc) {
if (err) return done(err);
assert.ok(doc.o._id);
assert.ok(doc.cats[0]);
assert.ok(doc.cats[0]._id);
assert.ok(doc.a[0]);
assert.ok(doc.a[0]._id);
done();
})
}
}
})
});

0 comments on commit 66e2224

Please sign in to comment.