Automattic / mongoose

MongoDB object modeling designed to work in an asynchronous environment.
https://mongoosejs.com
MIT License
26.97k stars 3.84k forks source link

Cloning a schema does not seem to clone virtuals #6133

Closed asabhaney closed 6 years ago

asabhaney commented 6 years ago

Do you want to request a feature or report a bug? Bug

What is the current behavior? When cloning a schema, virtuals defined on the original schema do not seem to be copied over to the new schema.

If the current behavior is a bug, please provide the steps to reproduce.

var assert = require('chai').assert
var mongoose = require('mongoose')
var Schema = require('mongoose/lib/schema');

describe('Schema.clone', function() {
  it('Correctly clones a schema virtual', function(done) {
      var UserSchema = new Schema({
         firstName: { type: String, required: true },
         lastName: { type: String, required: true }
      })

      UserSchema.virtual('fullName').get(function () {
         return this.firstName + ' ' + this.lastName
      })

      // Not really part of the test case, just for extra re-assurance
      UserSchema.methods.getFullName = function () {
         return this.firstName + ' ' + this.lastName
      }

      const User = mongoose.model('user', UserSchema)
      const user = new User()
      user.set({ firstName: 'Jane', lastName: 'Doe' })
      assert.equal(user.fullName, 'Jane Doe')

      const clonedUserSchema = UserSchema.clone()
      const ClonedUser = mongoose.model('user-clone', clonedUserSchema)
      const user2 = new ClonedUser()
      user2.set({ firstName: 'Jack', lastName: 'Doe' })

      // Passes!
      assert.equal(user2.firstName, 'Jack')
      assert.equal(user2.lastName, 'Doe')
      assert.equal(user2.getFullName(), 'Jack Doe') // the getter method works!

      // Failing :(
      assert.equal(user2.fullName, 'Jack Doe')

      done()
   })
})

Please mention your node.js, mongoose and MongoDB version. node 8.9.4, mongoose 5.0.4 (also tested against mongoose 4.13.11 and latest master)

ghost commented 6 years ago

Thanks for the complete repro script @asabhaney !!!! verified:

/Users/lineus/dev/Help/5/: mocha 6133.js 

  Schema.clone
    1) Correctly clones a schema virtual

  0 passing (33ms)
  1 failing

  1) Schema.clone
       Correctly clones a schema virtual:
     ReferenceError: clonedUserSchema is not defined
      at Context.<anonymous> (6133.js:25:17)

in schema.js:

Schema.prototype.clone = function() {
  var s = new Schema(this.paths, this.options);
  // Clone the call queue
  var cloneOpts = {};
  s.callQueue = this.callQueue.map(function(f) { return f; });
  s.methods = utils.clone(this.methods, cloneOpts);
  s.statics = utils.clone(this.statics, cloneOpts);
  s.query = utils.clone(this.query, cloneOpts);
  s.plugins = Array.prototype.slice.call(this.plugins);
  s._indexes = utils.clone(this._indexes, cloneOpts);
  s.s.hooks = this.s.hooks.clone();
  return s;
};

and schema.test.js:

it('clone() copies methods, statics, and query helpers (gh-5752)', function(done) {
...
it('clone() copies validators declared with validate() (gh-5607)', function(done) {

@vkarpov15 I can tackle this as long as the exclusion of virtuals wasn't intentional.

vkarpov15 commented 6 years ago

Thanks for reporting, will fix ASAP :+1: