Yasser
Yasser

Reputation: 1808

Why does backbone.js model.save() change the attribute hash?

I am doing something like this in my code:

data_hash = {};
data_hash['some_model_key'] = 'A';
console.log(data_hash['some_model_key']); /* prints A */
model.save(data_hash,{
    wait:true,
    success:function(){
        console.log(data_hash['some_model_key']); /* prints B */
    }
});                  

I understand that if the server changes the state of the model and i am setting wait:true then my backbone model should receive the new value. But why is my attribute hash being changed?

Upvotes: 4

Views: 2808

Answers (1)

nikoshr
nikoshr

Reputation: 33344

Why Backbone changes your object

If you take a look at the annotated source code, you'll notice that in case of a wait:true option, the success callback extends the attr object with the server attributes.

    if (options.wait) {
      delete options.wait;
      serverAttrs = _.extend(attrs || {}, serverAttrs);
    }

And according to Underscore doc, _.extend copies all of the properties in the source objects over to the destination object, overriding any previously defined property. Why it is the chosen behavior is a guess, but I suspect it is to keep all references in sync with the "real" state of the model. Or it's an unforeseen side effect.

Note that the first object you pass to model.save is expected to be attributes you want to set on your model as part of the save process. From Backbone doc

save model.save([attributes], [options])
The attributes hash (as in set) should contain the attributes you'd like to change — keys that aren't mentioned won't be altered — but, a complete representation of the resource will be sent to the server.

What you can do to keep your object untouched

Pass a clone of your object to model.save:

model.save(_.clone(data_hash), ...)

Note: you don't need to have a wait:true option for your model to receive the values from your server, model.set will be always be called with the new values.

Upvotes: 3

Related Questions