I'm using ember-data for a project of mine and I have a question that revolves around the possibility of dirtying an object and then setting its state to clean again on purpose - without commiting the changes. The scenario is this:
Say I've fetched an object via banana = App.Fruit.find('banana');
and it has a description of "Yellow fruit!". Using XHR long-polling (or WebSockets), I may receive an updated version of the object because of another user having changed the description to "A tasty yellow fruit!" at any given point in time after I fetched the original object.
Then, what I would like to do is to update the object to reflect the newly received data. For this, I've tried different approaches:
I've tried calling App.Store.load(App.Fruit, new_data);
. First of all, this approach doesn't work and secondly, this is not really what I want. I could've made uncommitted changes to the object myself and in this case, it would be undesirable to just discard those (assuming the load()
call would overwrite them).
I've tried looping through the new data, calling .set()
- like so: banana.set('description', new_data.description);
- in order to update the object properties with the new data (where applicable = not dirty). This works but it leaves the object in a dirtied state.
In order to make the object clean/updated again - and not have the adapter commit the changes! - I've taken a look at the states the object travels through. These are (at least):
rootState.loaded.saved
state..set()
on a property pushes it to the rootState.loaded.updated.uncommitted
state.App.store.commit();
returns the object to the rootState.loaded.saved
state.Therefore, I've tried to manually set the object state to saved
after step 2 like so: banana.get('stateManager').goToState('saved');
.
However, this doesn't work. The next time the store commits for any other reason, this maneuver produces an inFlightDirtyReasons is undefined error.
My question is: how can I manually change the state of a dirtied object back to clean (saved) again?
Solution for Ember Data 1.0.0-beta.7:
// changing to loaded.updated.inFlight, which has "didCommit"
record.send('willCommit');
// clear array of changed (dirty) model attributes
record.set('_attributes', {});
// changing to loaded.saved (hooks didCommit event in "inFlight" state)
record.send('didCommit');
I've searched the source code of Ember-data and I've found that loaded.saved state has a setup function that checks whether a model is clean, before setting "saved" state. If it is not clean, then it rejects a request to change state and returns to loaded.updated.uncommitted.
So you have to clean model._attributes array, which keeps attributes names and Ember will let you change state manually.
I know it isn't very good solution, because is needed to set private property of a model, but I've not found any other solutions yet.