Skip to content

Commit

Permalink
fix(schema): support setting discriminator options in Schema.prototyp…
Browse files Browse the repository at this point in the history
…e.discriminator()

Fix #14448
  • Loading branch information
vkarpov15 committed Apr 2, 2024
1 parent 9afba5f commit f845fb2
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 5 deletions.
7 changes: 5 additions & 2 deletions lib/helpers/discriminator/applyEmbeddedDiscriminators.js
Expand Up @@ -20,9 +20,12 @@ function applyEmbeddedDiscriminators(schema, seen = new WeakSet()) {
continue;
}
for (const discriminatorKey of schemaType.schema._applyDiscriminators.keys()) {
const discriminatorSchema = schemaType.schema._applyDiscriminators.get(discriminatorKey);
const {
schema: discriminatorSchema,
options
} = schemaType.schema._applyDiscriminators.get(discriminatorKey);
applyEmbeddedDiscriminators(discriminatorSchema, seen);
schemaType.discriminator(discriminatorKey, discriminatorSchema);
schemaType.discriminator(discriminatorKey, discriminatorSchema, options);
}
schemaType._appliedDiscriminators = true;
}
Expand Down
6 changes: 5 additions & 1 deletion lib/index.js
Expand Up @@ -628,7 +628,11 @@ Mongoose.prototype._model = function(name, schema, collection, options) {

if (schema._applyDiscriminators != null) {
for (const disc of schema._applyDiscriminators.keys()) {
model.discriminator(disc, schema._applyDiscriminators.get(disc));
const {
schema: discriminatorSchema,
options
} = schema._applyDiscriminators.get(disc);
model.discriminator(disc, discriminatorSchema, options);
}
}

Expand Down
10 changes: 8 additions & 2 deletions lib/schema.js
Expand Up @@ -624,12 +624,18 @@ Schema.prototype.defaultOptions = function(options) {
*
* @param {String} name the name of the discriminator
* @param {Schema} schema the discriminated Schema
* @param {Object} [options] discriminator options
* @param {String} [options.value] the string stored in the `discriminatorKey` property. If not specified, Mongoose uses the `name` parameter.
* @param {Boolean} [options.clone=true] By default, `discriminator()` clones the given `schema`. Set to `false` to skip cloning.
* @param {Boolean} [options.overwriteModels=false] by default, Mongoose does not allow you to define a discriminator with the same name as another discriminator. Set this to allow overwriting discriminators with the same name.
* @param {Boolean} [options.mergeHooks=true] By default, Mongoose merges the base schema's hooks with the discriminator schema's hooks. Set this option to `false` to make Mongoose use the discriminator schema's hooks instead.
* @param {Boolean} [options.mergePlugins=true] By default, Mongoose merges the base schema's plugins with the discriminator schema's plugins. Set this option to `false` to make Mongoose use the discriminator schema's plugins instead.
* @return {Schema} the Schema instance
* @api public
*/
Schema.prototype.discriminator = function(name, schema) {
Schema.prototype.discriminator = function(name, schema, options) {
this._applyDiscriminators = this._applyDiscriminators || new Map();
this._applyDiscriminators.set(name, schema);
this._applyDiscriminators.set(name, { schema, options });

return this;
};
Expand Down
19 changes: 19 additions & 0 deletions test/schema.test.js
Expand Up @@ -72,6 +72,7 @@ describe('schema', function() {
},
b: { $type: String }
}, { typeKey: '$type' });
db.deleteModel(/Test/);
NestedModel = db.model('Test', NestedSchema);
});

Expand Down Expand Up @@ -3202,4 +3203,22 @@ describe('schema', function() {
const doc = new baseModel({ type: 1, self: [{ type: 1 }] });
assert.equal(doc.self[0].type, 1);
});

it('handles discriminator options with Schema.prototype.discriminator (gh-14448)', async function() {
const eventSchema = new mongoose.Schema({
name: String
}, { discriminatorKey: 'kind' });
const clickedEventSchema = new mongoose.Schema({ element: String });
eventSchema.discriminator(
'Test2',
clickedEventSchema,
{ value: 'click' }
);
const Event = db.model('Test', eventSchema);
const ClickedModel = db.model('Test2');

const doc = await Event.create({ kind: 'click', element: '#hero' });
assert.equal(doc.element, '#hero');
assert.ok(doc instanceof ClickedModel);
});
});

0 comments on commit f845fb2

Please sign in to comment.