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

changedAttributes return entire deep object instead of only the changed field #74

Open
ericchaves opened this issue Feb 20, 2013 · 9 comments
Labels

Comments

@ericchaves
Copy link

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?
@afeld
Copy link
Owner

afeld commented Feb 20, 2013

Mind submitting a failing test?

@ericchaves
Copy link
Author

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

@jabbett
Copy link

jabbett commented Mar 28, 2013

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.

@afeld
Copy link
Owner

afeld commented Mar 28, 2013

Again, a pull request with a test case that can be worked against would be super helpful. Thanks!

@jabbett
Copy link

jabbett commented Mar 28, 2013

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?

@afeld
Copy link
Owner

afeld commented Mar 28, 2013

Ah, gotcha. See #72.

@gkatsev
Copy link
Collaborator

gkatsev commented Jan 11, 2014

Backbone 1.x (and 0.9.9) support has landed in master. Can you retest and see whether this is still a problem?

@alebedev
Copy link

Still happens with backbone 1.1.0 and backbone-nested 2.0.0

@alebedev
Copy link

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     

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

5 participants