How Do You Transition Rollback on a Model in an Error State?

I’ve been trying to find a simple, clean way to rollback a model in a RESTAdapter application if the record returns an error.

For example I have a model that I want to edit. If the REST request to put/update that model’s record on the server fails the current model’s view still reflects the changes made during the update. I’ve been able to successfully flash a warning using the “becameError” in the model, but I’d like a way rollback the failed model to display the data it last received before making a request to the server.

EDIT: Fri Apr 19 12:55:38 PDT 2013

Just read on the github site’s “Roadmap” section that Handling Error States is not yet implemented. Guess, I should have read the documentation more clearly. I would still like to hear from anyone else that has figured out creative ways of handling error states.

I think I was dealing with the same problem. It seemed like after I tried to save a model instance by calling .commit(), I could no longer do anything with the record because it was considered “invalid” (eg. the server responds with 422).

To get around this, I added one line to my model in the becameInvalid() callback that resets the status to valid so that I can try saving the record again. Here is what it looks like:

App.User = DS.Model.extend({

  becameInvalid: function(model) {
    model.send('becameValid');
  }

});

There are probably good reasons why you don’t want to do this, but it appears to be working fine for my use case.

Note: just read your explanation again, and you probably want to use the becameError callback…

Thanks Emerson, but the model still returns true for “isError” while reading false for “isDirty”.

Is there an effective way to prevent the model view from displaying data entered by the client side that failed when trying to upload to the server/persistence side?

As a footnote, I can pass an error message in the Model’s becameError callback, but no way to rollback to the data retrieved from the record from the last successful server request.

My use case is that a user may be logged in on multiple browser tabs, but logs out on one. The desirable behavior would be that if the user were to try to edit records an open tab would see a message that their record didn’t update and then have the displayed data would revert to what the last successful server request. This would also be useful if a user went offline without knowing it and would know that their work wasn’t being saved on the server.

I wish I could help, but my knowledge of ember-data is actually pretty limited at the moment. Hopefully someone else will come along and weight in!

I’m running into this same problem and I’d love to find a fix for it.

A commit will indeed not work after a becameError or becameInvalid state. You first need to go back to the uncommitted state and you can do that by using the transitionTo method on the transaction. See this post for detailed info: ember.js - Ember: transaction.commit does not fire after becameInvalid event - Stack Overflow

Please note that after a becameInvalid state and a transition back to the uncommitted state, the transaction is moved to the defaultTransaction and any subsequent commits thus need to be done on the defaultTransaction. In case of becameError, this is not the case …

My conclusion is that this leads to lots of very dirty code … And this is not something you need in the most important part of your application: i.e. The data synchronisatin with the server.