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

Previous Attributes after save() call #326

Closed
jgable opened this issue Apr 22, 2014 · 13 comments
Closed

Previous Attributes after save() call #326

jgable opened this issue Apr 22, 2014 · 13 comments
Labels

Comments

@jgable
Copy link
Contributor

jgable commented Apr 22, 2014

I'm trying to get the previous attributes after calling save() and having a hard time. Something like this is what I'd expect:

describe('previous, previousAttributes', function() {

  it('will return the previous value of an attribute the last time it was synced', function() {
    var model = new Models.Site({id: 1});
    return model.fetch().then(function() {
      return model.save({
        name: 'updatedknexjs.org'
      });
    })
    .then(function (u) {
      equal(model.get('name'), 'updatedknexjs.org');

      // This fails
      equal(model.previous('name'), 'knexjs.org');

      model.set('name', 'knexjs.org');

      return model.save();
    });

  });

});

Is there some other mechanism I can check after a save() call to get what attributes changed?

@tgriesser
Copy link
Member

Hmm, I don't know, I guess it depends on how you're trying to use "previous"... presumably you could do this:

var previous;
var model = new Models.Site({id: 1});
    return model.fetch().then(function() {
      previous = this.get('name')
      return model.save({
        name: 'updatedknexjs.org'
      });
    })
    .then(function (u) {
      equal(previous, 'knexjs.org');
      equal(model.get('name'), 'updatedknexjs.org');
      model.set('name', 'knexjs.org');
      return model.save();
    });

or this:

var previousAttrs;
var model = new Models.Site({id: 1});
    return model.fetch().then(function() {
      model.set(someValues)
      previousAttrs = this.previousAttributes();
      return model.save();
    })
    .then(function (u) {
      // compare previousAttrs here
      equal(model.get('name'), 'updatedknexjs.org');
      return model.save();
    });

would either of these work?

@jgable
Copy link
Contributor Author

jgable commented Apr 22, 2014

The use case is for TryGhost/Ghost#1563, we need to try and detect when a Post's status is changed from draft to published in order to set a X-Cache-Invalidate header on the request.

I'm thinking of listening to the saving and saved listeners and just assigning a this.updatedAttributes or something for comparing.

I'll try to report back if that works.

@tgriesser
Copy link
Member

In the saved event, it puts the previousAttributes on the options object incase you need them for something like this: link

@jgable
Copy link
Contributor Author

jgable commented Apr 22, 2014

I ended up adding the following to our base models and it seems to provide the functionality I'm looking for:

saving: function (newObj, attr, options) {
    // Store the previous attributes so we can tell what was updated later
    this._updatedAttributes = newObj.previousAttributes();
},

// Get attributes that have been updated (values before a .save() call)
updatedAttributes: function () {
    return this._updatedAttributes || {};
},

// Get a specific updated attribute value
updated: function (attr) {
    return this.updatedAttributes()[attr];
}

I couldn't get the options.previousAttributes to work for me, but this approach seems to be working.

@jgable jgable closed this as completed Apr 22, 2014
@tgriesser
Copy link
Member

Cool.

@gaastonsr
Copy link

This is a bug right? I'm having the same problem, I do:

/* user has "jdoe" as nickname */

user.save({
    nickname: 'updated'
})
.then(function(model) {
    console.log(model.previous('nickname'));
});

And I get "updated", is not supposed to return "jdoe"?

@thetutlage
Copy link

Not working , i have tried using all the hooks , saving ,saved , updating , updated and previousAttributes are blank in every case

@gaastonsr
Copy link

Do you have a test case so we can help you?

@thetutlage
Copy link

Yes

UserModel

bookshelf.model("Users",{
   initialize: function(){
        this.on("creating", this._beforeCreate, this);
        this.on("created", this._afterCreate, this);
        this.on("updating", this._beforeUpdate, this);
        this.on("updated", this._afterUpdate, this);
   },
   _beforeUpdate: function(model,attrs,options){
       console.log('model>>>>>',model);
       console.log('options>>>>>',options);
   },
   _afterUpdate: function(model,response,options){
       console.log('after:model>>>>>',model);
       console.log('after:options>>>>>',options);
   }
});

Now i will paste the console output from my unit tests

After update
screen shot 2015-02-27 at 9 49 56 pm
screen shot 2015-02-27 at 9 49 40 pm

Before update
screen shot 2015-02-27 at 9 49 21 pm
screen shot 2015-02-27 at 9 48 44 pm

Old email in my database was user@example.com which i updated with new@example.com

Update Query

      var data_object = {email_address:'new@example.com',email_verified:false};
      return self.model.forge({id:user_id})
      .save(data_object,{patch: true});

Here self.model is something inside collection

@gaastonsr
Copy link

I confirmed a while back that previousAttributes has a bug. I don't know if that claim is still valid. I would recommend you to workaround the problem by saving your attributes before your actions and make use of them later as it they were extracted from previous attributes.

var previousAttributes = model.toJSON();

// your actions
model.update();

// and later use them
console.log(previousAttributes.email); // old email!

@awHamer
Copy link

awHamer commented Jul 23, 2015

+1 After model is saved I'm expecting that previous attributes would be exactly previous attributes, but I got the same data that I set in update request

@aef-
Copy link

aef- commented Oct 8, 2015

Can this be opened as a bug? I'm experiencing this in 0.8.2.

@rhys-vdw
Copy link
Contributor

rhys-vdw commented Oct 8, 2015

@aef- There's a lot going on here, could you open a new issue showing exact use case with expected and actual ouput.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants