Skip to content

Commit 4437d8e

Browse files
committed
fix: allow adding discriminators using Schema.prototype.discriminator() to subdocuments after defining parent schema
Fix #14109
1 parent d31310a commit 4437d8e

File tree

4 files changed

+62
-12
lines changed

4 files changed

+62
-12
lines changed

lib/index.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,16 @@ Mongoose.prototype._model = function(name, schema, collection, options) {
629629
}
630630
}
631631

632+
for (const path of Object.keys(schema.paths)) {
633+
const schemaType = schema.paths[path];
634+
if (!schemaType.schema || !schemaType.schema._applyDiscriminators) {
635+
continue;
636+
}
637+
for (const disc of schemaType.schema._applyDiscriminators.keys()) {
638+
schemaType.discriminator(disc, schemaType.schema._applyDiscriminators.get(disc));
639+
}
640+
}
641+
632642
return model;
633643
};
634644

lib/schema/SubdocumentPath.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,6 @@ function SubdocumentPath(schema, path, options) {
5555
this.$isSingleNested = true;
5656
this.base = schema.base;
5757
SchemaType.call(this, path, options, 'Embedded');
58-
if (schema._applyDiscriminators != null && !options?._skipApplyDiscriminators) {
59-
for (const disc of schema._applyDiscriminators.keys()) {
60-
this.discriminator(disc, schema._applyDiscriminators.get(disc));
61-
}
62-
}
6358
}
6459

6560
/*!

lib/schema/documentarray.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,6 @@ function DocumentArrayPath(key, schema, options, schemaOptions) {
8888

8989
this.$embeddedSchemaType.caster = this.Constructor;
9090
this.$embeddedSchemaType.schema = this.schema;
91-
92-
if (schema._applyDiscriminators != null && !options?._skipApplyDiscriminators) {
93-
for (const disc of schema._applyDiscriminators.keys()) {
94-
this.discriminator(disc, schema._applyDiscriminators.get(disc));
95-
}
96-
}
9791
}
9892

9993
/**
@@ -528,7 +522,7 @@ DocumentArrayPath.prototype.cast = function(value, doc, init, prev, options) {
528522

529523
DocumentArrayPath.prototype.clone = function() {
530524
const options = Object.assign({}, this.options);
531-
const schematype = new this.constructor(this.path, this.schema, { ...options, _skipApplyDiscriminators: true }, this.schemaOptions);
525+
const schematype = new this.constructor(this.path, this.schema, options, this.schemaOptions);
532526
schematype.validators = this.validators.slice();
533527
if (this.requiredValidator !== undefined) {
534528
schematype.requiredValidator = this.requiredValidator;

test/document.test.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12657,6 +12657,57 @@ describe('document', function() {
1265712657
);
1265812658
});
1265912659

12660+
it('handles embedded discriminators defined using Schema.prototype.discriminator after defining schema (gh-14109) (gh-13898)', async function() {
12661+
const baseNestedDiscriminated = new Schema({
12662+
type: { type: Number, required: true }
12663+
}, { discriminatorKey: 'type' });
12664+
12665+
class BaseClass {
12666+
whoAmI() {
12667+
return 'I am baseNestedDiscriminated';
12668+
}
12669+
}
12670+
BaseClass.type = 1;
12671+
12672+
baseNestedDiscriminated.loadClass(BaseClass);
12673+
12674+
class NumberTyped extends BaseClass {
12675+
whoAmI() {
12676+
return 'I am NumberTyped';
12677+
}
12678+
}
12679+
NumberTyped.type = 3;
12680+
12681+
class StringTyped extends BaseClass {
12682+
whoAmI() {
12683+
return 'I am StringTyped';
12684+
}
12685+
}
12686+
StringTyped.type = 4;
12687+
12688+
const containsNestedSchema = new Schema({
12689+
nestedDiscriminatedTypes: { type: [baseNestedDiscriminated], required: true }
12690+
});
12691+
12692+
// After `containsNestedSchema`, in #13898 test these were before `containsNestedSchema`
12693+
baseNestedDiscriminated.discriminator(1, new Schema({}).loadClass(NumberTyped));
12694+
baseNestedDiscriminated.discriminator('3', new Schema({}).loadClass(StringTyped));
12695+
12696+
class ContainsNested {
12697+
whoAmI() {
12698+
return 'I am ContainsNested';
12699+
}
12700+
}
12701+
containsNestedSchema.loadClass(ContainsNested);
12702+
12703+
const Test = db.model('Test', containsNestedSchema);
12704+
const instance = await Test.create({ type: 1, nestedDiscriminatedTypes: [{ type: 1 }, { type: '3' }] });
12705+
assert.deepStrictEqual(
12706+
instance.nestedDiscriminatedTypes.map(i => i.whoAmI()),
12707+
['I am NumberTyped', 'I am StringTyped']
12708+
);
12709+
});
12710+
1266012711
it('can use `collection` as schema name (gh-13956)', async function() {
1266112712
const schema = new mongoose.Schema({ name: String, collection: String });
1266212713
const Test = db.model('Test', schema);

0 commit comments

Comments
 (0)