Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for "Apply defaults after setting initial value" doesn't work when documents are loaded via a query #7182

Closed
putermancer opened this issue Oct 25, 2018 · 1 comment
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Milestone

Comments

@putermancer
Copy link

putermancer commented Oct 25, 2018

PR #6119 for issue #3781 addressed an issue that caused the context object (this) provided to default function callback handlers to only have access to properties set in other default handlers, not the contents of the document itself. This works when creating a document, but it does not work when loading a document via a query. This causes problems where we are trying to do conditional defaults—based on another property, the default value should either be changed or removed entirely.

Another ticket was opened about this issue and closed because no code samples were provided (
#6330). I'm pretty sure this is the same issue I'm having.

The code snippet below reproduces the current behavior, with assertions for what is expected to happen. The second assertion fails because this.type was undefined in the default callback function.

Tested using Node 8.11.3, mongoose 5.3.6, mongo 3.4.2.

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const schema = new Schema({ type: String, choices: String });
schema.path('choices').default(function () {
  return this.type === 'mc' ? 'ABCDE' : this.type === 'rubric' ? '12345' : 'ERROR';
});

const Model = mongoose.model('Test', schema);

async function run() {
  await mongoose.connect('mongodb://localhost:27017/test');
  await mongoose.connection.dropDatabase();

  const created = new Model({ type: 'mc', id: 1 });
  await created.save();
  assert.equal(created.choices, 'ABCDE'); // works

  // clear it out to test what happens when a loaded document needs a default
  await Model.collection.updateOne({_id: created._id}, {$set: {type: 'rubric'}, $unset: {choices: 1}});
  const loaded = await Model.findById(created._id).exec();
  assert.equal(loaded.choices, '12345'); // fails because `this` was an empty object in default handler
}

run().catch(error => console.error(error.stack));
@vkarpov15 vkarpov15 added this to the 5.3.9 milestone Oct 30, 2018
@vkarpov15
Copy link
Collaborator

Thanks for reporting, will investigate asap 👍

@vkarpov15 vkarpov15 added the confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. label Oct 30, 2018
vkarpov15 added a commit that referenced this issue Nov 1, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Projects
None yet
Development

No branches or pull requests

2 participants