Observing Ember Objects for dirty checking


#1

I’m working on a new project using Ember 1.9 without Ember Data. Sure, ember-data is a powerful library and all that but after studying different adapters currently available I decided not to use it in production. There are other tools like Ember-Model, Ember-Orbit etc. but I decided to define my models by extending Ember.Object and write a thin layer on top of it (mixins, helpers etc.).

Currently, one of our requirements is to detect models’ dirtiness, so that we can send only the dirty properties across the wire. I’ve spent some time on the internet and haven’t seen anything useful yet. how might one approach this? attaching observers on every property doesn’t sound good, plus it won’t be effective for dirty checking. Ember-data and Ember-model both offer such functionality but considering that I’m not gonna be using such libraries, how can i achieve this effectively? Is it even possible with the current version of Ember and the state of JavaScript?

P.S detailed explanations, examples and online references are much appreciated! Thanks in advance


#2

I think you should keep the original data in a _data property. When you have to dirty check you compare the current set of properties to the original _data.

This also gives you rollback to the original _data if needed.

As for the implementation, create a property that will look for the property name on the object, if not present, use the property on _data.

I think that is pretty much what ember-data, ember-model are doing anyway.


#3

Thanks julien Just as i thought, so I’ll have to store a copy of my original data and the isDirty property will simply compare the values. one more thing, i don’t think i fully understand this paragraph:

As for the implementation, create a property that will look for the property name on the object, if not present, use the property on _data.

Would you explain this please. thanks again


#4

This is what I ended up doing:

  • Add a property to your model object to hold the original data (i.e. original_data)
  • Add a function called isDirty to your model object (more on this later)
  • When adding a new record, this property will be null. so in the isDirty function we’ll loop through the properties and see if their values are null. if so, we’ll add the property key to an array (i.e. dirtyProps[])
  • When updating an existing record, we’ll loop through the properties and compare their values to the original data. if they’re not the same, add the property key to an array.
  • Finally, we’ll return the aforementioned array which holds the dirty properties.

And this is the function I used to iterate over property keys:

App.YourModel.reopen({
    getPropertyKeys: function() {
        var self = this;
        var propKeys = {};

        for (var key in self.__proto__) {
            if (key === 'isInstance' ||
                key === 'isDestroyed' ||
                key === 'isDestroying' ||
                key === 'concatenatedProperties' ||
                key === '_super' ||
                typeof self[key] === 'function') {
                continue;
            }
            propKeys[key] = key;
        }

        return propKeys;
    }
});

This approach works fine for now, but I’ll definitely update this topic with a better implementation if I came across any :smile:


#5

So, I made my own solution, probably nit the best one, but it works good!

I have a mixin that can create hashes and compare them. Everytime a model loads in the route, I save these model hashes and everytime I save models I update them. The mixin overrides the willTransition method and there I check if the model (the hash) changed.