Skip to content

Commit

Permalink
feat(document): support defaults option to disable adding defaults …
Browse files Browse the repository at this point in the history
…to a single document

Fix #8271
  • Loading branch information
vkarpov15 committed Jun 14, 2020
1 parent cb3a19a commit 9609e87
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 8 deletions.
19 changes: 12 additions & 7 deletions lib/document.js
Expand Up @@ -55,7 +55,8 @@ const specialProperties = utils.specialProperties;
*
* @param {Object} obj the values to set
* @param {Object} [fields] optional object containing the fields which were selected in the query returning this document and any populated paths data
* @param {Boolean} [skipId] bool, should we auto create an ObjectId _id
* @param {Object} [options] various configuration options for the document
* @param {Boolean} [options.defaults=true] if `false`, skip applying default values to this document.
* @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter
* @event `init`: Emitted on a document after it has been retrieved from the db and fully hydrated by Mongoose.
* @event `save`: Emitted when the document is successfully saved
Expand All @@ -67,7 +68,9 @@ function Document(obj, fields, skipId, options) {
options = skipId;
skipId = options.skipId;
}
options = options || {};
options = Object.assign({}, options);
const defaults = get(options, 'defaults', true);
options.defaults = defaults;

// Support `browserDocument.js` syntax
if (this.schema == null) {
Expand Down Expand Up @@ -126,9 +129,11 @@ function Document(obj, fields, skipId, options) {

// By default, defaults get applied **before** setting initial values
// Re: gh-6155
$__applyDefaults(this, fields, skipId, exclude, hasIncludedChildren, true, {
isNew: this.isNew
});
if (defaults) {
$__applyDefaults(this, fields, skipId, exclude, hasIncludedChildren, true, {
isNew: this.isNew
});
}
}

if (obj) {
Expand All @@ -147,13 +152,13 @@ function Document(obj, fields, skipId, options) {
// Function defaults get applied **after** setting initial values so they
// see the full doc rather than an empty one, unless they opt out.
// Re: gh-3781, gh-6155
if (options.willInit) {
if (options.willInit && defaults) {
EventEmitter.prototype.once.call(this, 'init', () => {
$__applyDefaults(this, fields, skipId, exclude, hasIncludedChildren, false, options.skipDefaults, {
isNew: this.isNew
});
});
} else {
} else if (defaults) {
$__applyDefaults(this, fields, skipId, exclude, hasIncludedChildren, false, options.skipDefaults, {
isNew: this.isNew
});
Expand Down
5 changes: 4 additions & 1 deletion lib/types/subdocument.js
Expand Up @@ -29,7 +29,10 @@ function Subdocument(value, fields, parent, skipId, options) {
}
if (parent != null) {
// If setting a nested path, should copy isNew from parent re: gh-7048
options = Object.assign({}, options, { isNew: parent.isNew });
options = Object.assign({}, options, {
isNew: parent.isNew,
defaults: parent.$__.$options.defaults
});
}
Document.call(this, value, fields, skipId, options);

Expand Down
21 changes: 21 additions & 0 deletions test/document.test.js
Expand Up @@ -8975,4 +8975,25 @@ describe('document', function() {
const axl = new Person({ fullName: 'Axl Rose' });
assert.equal(axl.fullName, 'Axl Rose');
});

it('supports skipping defaults on a document (gh-8271)', function() {
const testSchema = new mongoose.Schema({
testTopLevel: { type: String, default: 'foo' },
testNested: {
prop: { type: String, default: 'bar' }
},
testArray: [{ prop: { type: String, defualt: 'baz' } }],
testSingleNested: new Schema({
prop: { type: String, default: 'qux' }
})
});
const Test = db.model('Test', testSchema);

const doc = new Test({ testArray: [{}], testSingleNested: {} }, null,
{ defaults: false });
assert.ok(!doc.testTopLevel);
assert.ok(!doc.testNested.prop);
assert.ok(!doc.testArray[0].prop);
assert.ok(!doc.testSingleNested.prop);
});
});

0 comments on commit 9609e87

Please sign in to comment.