Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Persisting non schema values between hooks #2952

Closed
bshamblen opened this issue May 1, 2015 · 1 comment
Closed

Persisting non schema values between hooks #2952

bshamblen opened this issue May 1, 2015 · 1 comment

Comments

@bshamblen
Copy link

Previously (similar to #2363) I was storing a copy of the existing doc in the post init hook, then in the pre save hook I compared the original doc with the updated doc (if not new), then in the post save hook I had logic to send a notification of the changes.

Before I upgraded to 4.0, the code below used to work (I don't recall which version of 3.8 I was using), but now I receive the error message Object #<EventEmitter> has no method 'toObject' when trying to copy the current object. I've been trying to come up with a workable solution, but I can't see a way to persist the original document through to the post save event.

My original code (3.8.x)

schema.post('init', function() {
    this._original = this.toObject();
    this._changes = []; //array of objects with the path, new and old values. Populated by `observe` function in pre `save` hook
});

schema.pre('save', function(next) {
    //other logic here. Cut out for this example..

    this.observe(); //compares the current doc with the original and stores the new and old values in `this._changes` array.
    next();
});

schema.post('save', function(doc) {
    if (this._original && this._changes.length > 0) {
        //send web hook notification, with changes
    } else {
        //send web hook notification, with new document
    }

    //reset the values, in case the document is saved again.
    this._original = null;
    this._original = this;
    this._changes = [];
});

The problem with the new post init architecture is that when I add the doc parameter to the hook function I can get the doc and add a copy to itself, but that copy will no longer be available in the pre or post save hooks.

Changed to (4.0.x)

schema.post('init', function(doc) {
    doc._original = doc.toObject();
    doc._changes = [];
});

Later, in the pre save hook, this._original is undefined, even for documents that we returned from the database. Any suggestions on how to reliably save a copy of the original document and have it survive the document lifecycle.

@vkarpov15 vkarpov15 added this to the 4.0.4 milestone May 1, 2015
@vkarpov15
Copy link
Collaborator

This issue is another manifestation of #2949 and #2925, accidental regression in 4.0.2 that occurred when we theoretically brought back the ability to do:

schema.post('init', function() {
    this._original = this.toObject();
    this._changes = []; //array of objects with the path, new and old values. Populated by `observe` function in pre `save` hook
});

You should be able to do that again in 4.0.3, the below script works for me on 4.0.3:

var mongoose = require('mongoose');
mongoose.set('debug', true);
var util = require('util');
var assert = require('assert');

mongoose.connect('mongodb://localhost:27017/gh2952');

var UserSchema = new mongoose.Schema({
  name: { type: String },
});

UserSchema.post('init', function(doc) {
console.log('post init');
  doc._original = doc.toObject();
});

var User = mongoose.model('user', UserSchema);

User.create({ name: 'val' }, function(error) {
  assert.ifError(error);
  User.findOne({}, function(error, u) {
    console.log(require('util').inspect(u._original));
    process.exit(0);
  });
});

@vkarpov15 vkarpov15 removed this from the 4.0.4 milestone May 15, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants