Skip to content

Commit

Permalink
fix: apply embedded discriminators to subdoc schemas before compiling…
Browse files Browse the repository at this point in the history
… top level model so middleware applies correctly

Fix #14961
  • Loading branch information
vkarpov15 committed Nov 1, 2024
1 parent 10a3aed commit 6a73d25
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 2 deletions.
4 changes: 2 additions & 2 deletions lib/mongoose.js
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,8 @@ Mongoose.prototype._model = function(name, schema, collection, options) {
utils.toCollectionName(name, _mongoose.pluralize());
}

applyEmbeddedDiscriminators(schema);

const connection = options.connection || _mongoose.connection;
model = _mongoose.Model.compile(model || name, schema, collection, connection, _mongoose);
// Errors handled internally, so safe to ignore error
Expand All @@ -678,8 +680,6 @@ Mongoose.prototype._model = function(name, schema, collection, options) {
}
}

applyEmbeddedDiscriminators(schema);

return model;
};

Expand Down
62 changes: 62 additions & 0 deletions test/document.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12996,6 +12996,68 @@ describe('document', function() {
);
});

it('handles middleware on embedded discriminators on nested path defined using Schema.prototype.discriminator (gh-14961)', async function() {
const eventSchema = new Schema(
{ message: String },
{ discriminatorKey: 'kind', _id: false }
);

const clickedSchema = new Schema({
element: String
}, { _id: false });

// This is the discriminator which we will use to test middleware
const purchasedSchema = new Schema({
product: String
}, { _id: false });

let eventSchemaPreValidateCalls = 0;
let eventSchemaPreSaveCalls = 0;
eventSchema.pre('validate', function() {
++eventSchemaPreValidateCalls;
});
eventSchema.pre('save', function() {
++eventSchemaPreSaveCalls;
});

let purchasedSchemaPreValidateCalls = 0;
let purchasedSchemaPreSaveCalls = 0;
purchasedSchema.pre('validate', function() {
++purchasedSchemaPreValidateCalls;
});
purchasedSchema.pre('save', function() {
++purchasedSchemaPreSaveCalls;
});

eventSchema.discriminator('Clicked', clickedSchema);
eventSchema.discriminator('Purchased', purchasedSchema);

const trackSchema = new Schema({
event: eventSchema
});

// Test

const MyModel = db.model('track', trackSchema);
const doc = new MyModel({
event: {
kind: 'Purchased',
message: 'Test',
product: 'iPhone'
}
});

await doc.save();
assert.equal(doc.event.message, 'Test');
assert.equal(doc.event.kind, 'Purchased');
assert.equal(doc.event.product, 'iPhone');

assert.strictEqual(eventSchemaPreValidateCalls, 1);
assert.strictEqual(eventSchemaPreSaveCalls, 1);
assert.strictEqual(purchasedSchemaPreValidateCalls, 1);
assert.strictEqual(purchasedSchemaPreSaveCalls, 1);
});

it('handles reusing schema with embedded discriminators defined using Schema.prototype.discriminator (gh-14162)', async function() {
const discriminated = new Schema({
type: { type: Number, required: true }
Expand Down

0 comments on commit 6a73d25

Please sign in to comment.