Persuant to my github issue what is the expected behaviour of a rollback after a previous save attempt returned a 422 error? I expected a reset to the last known valid state but got only the clearing of the isDirty flag with all properties remaining in their invalid state. Is anyone else seeing this behaviour?
I chatted with @wycats about this on IRC and it seems that the current behavior is intended. Rollback only reverts any uncommitted changes – which does not include invalid attributes after a save. I can see the appeal of this in some situations. You don’t necessarily want invalid values to “pop” back to their previously known state if you’re getting back validation errors.
Presumably, some sort of transaction would be more suited for the use case you’re talking about, but I didn’t get any answers about the intended plan for re-implementing transactions in Ember Data 1.0.0 and there doesn’t seem to be an alternative to .rollback() anywhere in the code right now.
In the mean time, I was able to return my model to the previously known valid, non-dirty, non-error state by issuing a second .save() after a second .set() that put the attributes back to their previous state. Not optimal but it works.
I can sort of see this, and I definitely don’t want it happening as soon as the server errors, but an explicit request to a model that isError to rollback in my mind should treat server marked invalid data exactly the same as any other local change, because assuming a server is king relationship (pretty common for CRUD) that’s essentially what it is, a local modification not yet persisted (successfully) to the actual “one source of truth”.
This is essentially the method I’m pursuing, but it feels pretty backwards.
Thanks for the clarification anyway.
I agree, but it doesn’t seem like an uncommon one.
I’m also investigating http://epf.io/ but the documentation is…minimal is perhaps kindest.
This is not the use case I refer to. I do not want to revert to initial values when the server returns an error. I do however want an “escape” path in such a situation. In my app this is implemented as a “cancel/revert” button. When the user clicks on this button I want that the origianl values are restored independent of the actions he did before (modified some fields, tried to save but server did return 422). It now looks that this is not possible or that I need to implement different code for rollback depending on the isError flag …
Can you provide a small code sample with the .set and .save. I am not familiar with .set … do not understand how a .set can set back old values …
Right, the current rollback only allows for an escape path before save() is called.
In my case, I’m simply flipping a “published” boolean from true back to false, so it’s literally just:
model.set("published", false).save()
in the failure callback of the original save(). If you’re looking to reset all of the model’s attributes (or a larger subset), you’ll have to store them somewhere before the model becomes dirty.
It does seem silly to have to make a second server trip when we know from the 422 response that the model was not updated. Am I wrong in thinking this is one of the intended uses of transactions (if/when they are re-integrated into Ember Data 1.0.0+)?
@amarpalsapure Amar, I am confused here. This post is about rollback of model changes after a unsuccesful save attempt … this has nothing to do with your change of the hasMany relationship. Or am I missing something ?
@amarpalsapure Thx - A more thorough rollback would indeed be appreciated.
I do not fully agree that this is a feature request and not a bug. The following is not a logic flow:
Change a model property so that it will fail when saving (isDirty =
true)
Save (isDirty = true and isError becomes true because the server returns a 422)
Click on “Revert changes” (thus do rollback) - the isDirty flag is set to false and isError remains true; but the model properties are not set back to their initial values
Save again (with exactly the same data); the server thus fails again with a 422
Now, rollback again: and now, the properties are set back to their initial value ! But the isError flag remains true.
This is thus in any case not a stable behavior …
For now I see 3 workarounds:
Store each model twice (keep a sort of read-only copy) so that in case of a 422 error and requesting a “revert changes” you can always revert to the copy you stored.
Include in the 422 error response the initial data and then set each model property to the values returned.
When clicking “revert changes”, clear the model and fetch the data again from the server.
But to be honest, I would nobody recommend implementing one of these methods … this is just what a client-side rollback should cover. But I also agree, this is not first priority !
I agree that we could use a “more thorough rollback”. It’s one of the things I will be working on soon after reviewing a number of open issues and posts on this forum.
I am also trying to build this functionality (rollback changes after a 422) into my app. I’m curious, does anyone have a reasonable workaround in the meantime?
I have actually find out that with Ember-data 1.0.beta8 when I try to save a record which is in state root.loaded.updated.uncommitted and it fails, on promise failure handler the model is still in the same state.
New data are stored in _inFlightAttributes object while, in _data object the original data are maintained.
A call to record.rollback() will in fact delete all data present in _inFlightAttributes and put the record in state root.loaded.saved
My error comes from a bad modification of the record attributes, which failed to put the record in root.loaded.updated.uncommitted state.