backbone-nested
backbone-nested copied to clipboard
changedAttributes return entire deep object instead of only the changed field
Hi there,
After updating a sub-set of nested properties, calling model.changedAttributes will return the entire object instead of only the changed ones.
var book = new Backbone.NestedModel.model({
title: 'abook',
author: {
first_name: 'Jane',
last_name: 'Doe'
},
category: 'Mistery'
});
book.save();
...
book.set({
title: 'TheBook',
author: {
first_name: 'Jhon'
}
});
console.log(book.changedAttributes());
/* printed result is
{
title: 'TheBook',
author: {
first_name: 'Jhon',
last_name: 'Doe'
}
}
*/
Would it be possible to just return the changedAttributes?
Mind submitting a failing test?
Hi Aidan,
I was going through your test cases so I could write one but I got a little confused about what your implementation of changedAttributes
actually works. I'm not very familiar with qunit so I may had misunderstood the tests. Please forgive me if so.
From Backbone docs, changedAttributes
should return only the changed fields, to be used, for example, in partial updates and partial syncs (by PATCHing an objetc).
Hence, assuming your test case scenario (and it's doc object) when we do an update, say doc.set({'name.middle.full': 'Limburger'});
, a call to changedAttributes
(assuming no previous updates was done in the doc) should return exactly that, right?
But according to your tests, the changedAttributes
returns a hash composed by the actual object plus other path's variants (test case 99, "#changedAttributes() should return the attributes for the full path and all sub-paths", line 647 of nested-model.js).
Also when I run my sample code, I got a totally different object from your tests. What I got seems to be a hash of all nested object that have any attributes changed (which is more than the expect hash of changed attributes only).
I'm sure I'm missing something here, but I can't got what it is. Would you care explaining what a call to NestedModel.changedAttributes
returns?
Thanks for the help,
Eric
I'm having this problem as well. changedAttributes correctly returns "false" when no fields have changed. But when I change a single field, changeAttributes returns the entire object.
Again, a pull request with a test case that can be worked against would be super helpful. Thanks!
Thanks for the motivation, I finally cracked open the test suite! It turns out that I'm seeing this problem because I'm using Backbone 0.9.9, not 0.9.2. Do you plan to support 0.9.9 or 1.0 soon?
Ah, gotcha. See #72.
Backbone 1.x (and 0.9.9) support has landed in master. Can you retest and see whether this is still a problem?
Still happens with backbone 1.1.0 and backbone-nested 2.0.0
Here's naive solution in coffeescript that I'm using as workaround
changedAttributes: ->
changes = super
getPreviousValue = (attrPath) =>
value = _.clone(this._previousAttributes)
for key in attrPath.split('.')
value = value?[key]
value
flatChanges = (changes, path) ->
result = {}
for key, value of changes
attrPath = _.compact([path, key]).join('.')
unless _.isObject(value)
unless value == getPreviousValue(attrPath)
result[attrPath] = value
else
_.extend(result, flatChanges(value, attrPath))
result
result = flatChanges(changes)
result