From c480bd6dbbad7682a05edd99353d0bac0d0c334a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 29 Jan 2024 12:42:12 -0500 Subject: [PATCH] feat(model): add `recompileSchema()` function to models to allow applying schema changes after compiling Fix #14296 --- lib/model.js | 28 ++++++++++++++++++++++++++++ test/model.test.js | 13 +++++++++++++ 2 files changed, 41 insertions(+) diff --git a/lib/model.js b/lib/model.js index 0ced344223a..b793218077f 100644 --- a/lib/model.js +++ b/lib/model.js @@ -4861,6 +4861,34 @@ Model.__subclass = function subclass(conn, schema, collection) { return Model; }; +/** + * Apply changes made to this model's schema after this model was compiled. + * By default, adding virtuals and other properties to a schema after the model is compiled does nothing. + * Call this function to apply virtuals and properties that were added later. + * + * #### Example: + * const schema = new mongoose.Schema({ field: String }); + * const TestModel = mongoose.model('Test', schema); + * TestModel.schema.virtual('myVirtual').get(function() { + * return this.field + ' from myVirtual'; + * }); + * const doc = new TestModel({ field: 'Hello' }); + * doc.myVirtual; // undefined + * + * TestModel.recompileSchema(); + * doc.myVirtual; // 'Hello from myVirtual' + * + * @return {Model} + * @api public + * @memberOf Model + * @static + * @method recompileSchema + */ + +Model.recompileSchema = function recompileSchema() { + this.prototype.$__setSchema(this.schema); +}; + /** * Helper for console.log. Given a model named 'MyModel', returns the string * `'Model { MyModel }'`. diff --git a/test/model.test.js b/test/model.test.js index edff29ae047..3bd48f7018d 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -7302,6 +7302,19 @@ describe('Model', function() { /First argument to `Model` constructor must be an object/ ); }); + + it('supports recompiling model with new schema additions (gh-14296)', function() { + const schema = new mongoose.Schema({ field: String }); + const TestModel = db.model('Test', schema); + TestModel.schema.virtual('myVirtual').get(function() { + return this.field + ' from myVirtual'; + }); + const doc = new TestModel({ field: 'Hello' }); + assert.strictEqual(doc.myVirtual, undefined); + + TestModel.recompileSchema(); + assert.equal(doc.myVirtual, 'Hello from myVirtual'); + }); });