Skip to content

Commit f9bfae0

Browse files
authored
Merge pull request #13858 from Automattic/vkarpov15/gh-13788
fix(schema): handle number discriminator keys when using `Schema.prototype.discriminator()`
2 parents 87619d0 + 4c38056 commit f9bfae0

File tree

3 files changed

+50
-12
lines changed

3 files changed

+50
-12
lines changed

lib/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -624,8 +624,8 @@ Mongoose.prototype._model = function(name, schema, collection, options) {
624624
connection.emit('model', model);
625625

626626
if (schema._applyDiscriminators != null) {
627-
for (const disc of Object.keys(schema._applyDiscriminators)) {
628-
model.discriminator(disc, schema._applyDiscriminators[disc]);
627+
for (const disc of schema._applyDiscriminators.keys()) {
628+
model.discriminator(disc, schema._applyDiscriminators.get(disc));
629629
}
630630
}
631631

lib/schema.js

+11-10
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ Schema.prototype._clone = function _clone(Constructor) {
449449
s.discriminators = Object.assign({}, this.discriminators);
450450
}
451451
if (this._applyDiscriminators != null) {
452-
s._applyDiscriminators = Object.assign({}, this._applyDiscriminators);
452+
s._applyDiscriminators = new Map(this._applyDiscriminators);
453453
}
454454

455455
s.aliases = Object.assign({}, this.aliases);
@@ -621,7 +621,8 @@ Schema.prototype.defaultOptions = function(options) {
621621
* @api public
622622
*/
623623
Schema.prototype.discriminator = function(name, schema) {
624-
this._applyDiscriminators = Object.assign(this._applyDiscriminators || {}, { [name]: schema });
624+
this._applyDiscriminators = this._applyDiscriminators || new Map();
625+
this._applyDiscriminators.set(name, schema);
625626

626627
return this;
627628
};
@@ -722,18 +723,18 @@ Schema.prototype.add = function add(obj, prefix) {
722723
for (const key in val[0].discriminators) {
723724
schemaType.discriminator(key, val[0].discriminators[key]);
724725
}
725-
} else if (val[0] != null && val[0].instanceOfSchema && utils.isPOJO(val[0]._applyDiscriminators)) {
726-
const applyDiscriminators = val[0]._applyDiscriminators || [];
726+
} else if (val[0] != null && val[0].instanceOfSchema && val[0]._applyDiscriminators instanceof Map) {
727+
const applyDiscriminators = val[0]._applyDiscriminators;
727728
const schemaType = this.path(prefix + key);
728-
for (const disc in applyDiscriminators) {
729-
schemaType.discriminator(disc, applyDiscriminators[disc]);
729+
for (const disc of applyDiscriminators.keys()) {
730+
schemaType.discriminator(disc, applyDiscriminators.get(disc));
730731
}
731732
}
732-
else if (val != null && val.instanceOfSchema && utils.isPOJO(val._applyDiscriminators)) {
733-
const applyDiscriminators = val._applyDiscriminators || [];
733+
else if (val != null && val.instanceOfSchema && val._applyDiscriminators instanceof Map) {
734+
const applyDiscriminators = val._applyDiscriminators;
734735
const schemaType = this.path(prefix + key);
735-
for (const disc in applyDiscriminators) {
736-
schemaType.discriminator(disc, applyDiscriminators[disc]);
736+
for (const disc of applyDiscriminators.keys()) {
737+
schemaType.discriminator(disc, applyDiscriminators.get(disc));
737738
}
738739
}
739740
} else if (Object.keys(val).length < 1) {

test/schema.test.js

+37
Original file line numberDiff line numberDiff line change
@@ -2873,6 +2873,43 @@ describe('schema', function() {
28732873
assert(batch.message);
28742874
});
28752875

2876+
it('supports numbers with Schema.discriminator() (gh-13788)', async() => {
2877+
const baseClassSchema = new Schema({
2878+
type: { type: Number, required: true }
2879+
}, { discriminatorKey: 'type' });
2880+
2881+
class BaseClass {
2882+
whoAmI() {
2883+
return 'I am base';
2884+
}
2885+
}
2886+
BaseClass.type = 1;
2887+
2888+
baseClassSchema.loadClass(BaseClass);
2889+
2890+
class NumberTyped extends BaseClass {
2891+
whoAmI() {
2892+
return 'I am NumberTyped';
2893+
}
2894+
}
2895+
NumberTyped.type = 2;
2896+
2897+
class StringTyped extends BaseClass {
2898+
whoAmI() {
2899+
return 'I am StringTyped';
2900+
}
2901+
}
2902+
StringTyped.type = '3';
2903+
2904+
baseClassSchema.discriminator(2, new Schema({}).loadClass(NumberTyped));
2905+
baseClassSchema.discriminator('3', new Schema({}).loadClass(StringTyped));
2906+
const Test = db.model('Test', { item: baseClassSchema });
2907+
let doc = await Test.create({ item: { type: 2 } });
2908+
assert.equal(doc.item.whoAmI(), 'I am NumberTyped');
2909+
doc = await Test.create({ item: { type: '3' } });
2910+
assert.equal(doc.item.whoAmI(), 'I am StringTyped');
2911+
});
2912+
28762913
it('can use on as a schema property (gh-11580)', async() => {
28772914
const testSchema = new mongoose.Schema({
28782915
on: String

0 commit comments

Comments
 (0)