Defaults are used when merging attributes during a Collection.set #2471
Description
Currently when you pass an attribute hash to Collection.set
, and a model with the same id already exists in the collection resulting in a merge, the Model's default values are applied before the merge takes place.
This means that if you give .set
a selection of attributes that you want to be merged into the model, any attributes that you don't give it, that have defaults defined, will override existing non-default values.
To me this seems very unexpected. Collection.set
seems like the perfect way to apply partial updates to models, but with the current functionality this isn't possible.
Example:
var Model = Backbone.Model.extend({
defaults: {
key: 'value'
}
});
var m = new Model({id: 1, key: 'nondefault'});
var col = new Backbone.Collection([m], {model: Model});
col.set({id: 1, otherkey: 'other'}, {merge: true});
console.log(col.first().attributes);
// result: {id: 1, key: "value", otherkey: "other"}
// expected: {id: 1, key: "nondefault", otherkey: "other"}
The confusing thing is that setting the attributes on the model directly behaves differently (the way I would have expected Collection.set
to behave):
var Model = Backbone.Model.extend({
defaults: {
key: 'value'
}
});
var m = new Model({id: 1, key: 'nondefault'});
m.set({id: 1, otherkey: 'other'})
console.log(m.attributes);
// result: {id: 1, key: "nondefault", otherkey: "other"}
Edit:
Actually, testing with 0.9.10, this seems to be a regression:
// Version 0.9.10
var Model = Backbone.Model.extend({
defaults: {
key: 'value'
}
});
var m = new Model({id: 1, key: 'nondefault'});
var col = new Backbone.Collection([m], {model: Model});
col.update({id: 1, otherkey: 'other'}, {merge: true});
console.log(col.first().attributes);
// result: {id: 1, key: "nondefault", otherkey: "other"}
Edit:
This commit seems to be the source of the change: a920fed
Was it really intended?