Skip to content

Commit

Permalink
fix(discriminator): allow numbers and ObjectIds as tied values for di…
Browse files Browse the repository at this point in the history
…scriminators

Fix #10130
  • Loading branch information
vkarpov15 committed Apr 28, 2021
1 parent 5c6359d commit c1cedd8
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 10 deletions.
4 changes: 2 additions & 2 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -603,8 +603,8 @@ declare module 'mongoose' {

interface AcceptsDiscriminator {
/** Adds a discriminator type. */
discriminator<D extends Document>(name: string | number, schema: Schema<D>, value?: string): Model<D>;
discriminator<T extends Document, U extends Model<T>>(name: string | number, schema: Schema<T, U>, value?: string): U;
discriminator<D extends Document>(name: string | number, schema: Schema<D>, value?: string | number | ObjectId): Model<D>;
discriminator<T extends Document, U extends Model<T>>(name: string | number, schema: Schema<T, U>, value?: string | number | ObjectId): U;
}

interface AnyObject { [k: string]: any }
Expand Down
16 changes: 16 additions & 0 deletions lib/helpers/discriminator/areDiscriminatorValuesEqual.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
'use strict';

const ObjectId = require('../../types/objectid');

module.exports = function areDiscriminatorValuesEqual(a, b) {
if (typeof a === 'string' && typeof b === 'string') {
return a === b;
}
if (typeof a === 'number' && typeof b === 'number') {
return a === b;
}
if (a instanceof ObjectId && b instanceof ObjectId) {
return a.toString() === b.toString();
}
return false;
};
12 changes: 6 additions & 6 deletions lib/helpers/discriminator/getDiscriminatorByValue.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

const areDiscriminatorValuesEqual = require('./areDiscriminatorValuesEqual');

/*!
* returns discriminator by discriminatorMapping.value
*
Expand All @@ -8,20 +10,18 @@
*/

module.exports = function getDiscriminatorByValue(model, value) {
let discriminator = null;
if (!model.discriminators) {
return discriminator;
return null;
}
for (const name in model.discriminators) {
const it = model.discriminators[name];
if (
it.schema &&
it.schema.discriminatorMapping &&
it.schema.discriminatorMapping.value == value
areDiscriminatorValuesEqual(it.schema.discriminatorMapping.value, value)
) {
discriminator = it;
break;
return it;
}
}
return discriminator;
return null;
};
4 changes: 3 additions & 1 deletion lib/helpers/discriminator/getSchemaDiscriminatorByValue.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

const areDiscriminatorValuesEqual = require('./areDiscriminatorValuesEqual');

/*!
* returns discriminator by discriminatorMapping.value
*
Expand All @@ -16,7 +18,7 @@ module.exports = function getSchemaDiscriminatorByValue(schema, value) {
if (discriminatorSchema.discriminatorMapping == null) {
continue;
}
if (discriminatorSchema.discriminatorMapping.value === value) {
if (areDiscriminatorValuesEqual(discriminatorSchema.discriminatorMapping.value, value)) {
return discriminatorSchema;
}
}
Expand Down
5 changes: 4 additions & 1 deletion lib/helpers/model/discriminator.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const Mixed = require('../../schema/mixed');
const ObjectId = require('../../types/objectid');
const defineKey = require('../document/compile').defineKey;
const get = require('../get');
const utils = require('../../utils');
Expand Down Expand Up @@ -63,7 +64,9 @@ module.exports = function discriminator(model, name, schema, tiedValue, applyPlu
}

let value = name;
if (typeof tiedValue == 'string' && tiedValue.length) {
if ((typeof tiedValue === 'string' && tiedValue.length) ||
typeof tiedValue === 'number' ||
tiedValue instanceof ObjectId) {
value = tiedValue;
}

Expand Down
29 changes: 29 additions & 0 deletions test/model.discriminator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,35 @@ describe('model', function() {
});
});

it('supports ObjectId as tied value (gh-10130)', function() {
const eventSchema = new Schema({ message: String, kind: 'ObjectId' },
{ discriminatorKey: 'kind' });

const Event = db.model('Event', eventSchema);
const clickedId = new mongoose.Types.ObjectId();
const purchasedId = new mongoose.Types.ObjectId();
Event.discriminator('Clicked', new Schema({
element: String
}), clickedId);
Event.discriminator('Purchased', new Schema({
product: String
}), purchasedId);

return co(function*() {
yield Event.create([
{ message: 'test', element: '#buy', kind: clickedId },
{ message: 'test2', product: 'Turbo Man', kind: purchasedId }
]);

const docs = yield Event.find().sort({ message: 1 });
assert.equal(docs.length, 2);
assert.equal(docs[0].kind.toHexString(), clickedId.toHexString());
assert.equal(docs[0].element, '#buy');
assert.equal(docs[1].kind.toHexString(), purchasedId.toHexString());
assert.equal(docs[1].product, 'Turbo Man');
});
});

it('Embedded discriminators in nested doc arrays (gh-6202)', function() {
const eventSchema = new Schema({ message: String }, {
discriminatorKey: 'kind',
Expand Down

0 comments on commit c1cedd8

Please sign in to comment.