David Monagle
David Monagle

Reputation: 1801

What can you do with Ember Data Models when in the error state?

I'm struggling to understand the workflow that would be used in the following scenario:

A user creates a model, let's call it Product. We present them with a form to fill in. The save errors for some reason other than validations (timeout, access denied etc...) In Ember, this puts the model into an error state. From a UI perspective, all I want to do is put a message on the screen (easy) and allow the user to try again (apparently not so easy).

I've seen it written many times not to reuse a transaction. I understand the logic of that. In the case of a new Product, I simple create another new Product, merge in the data from the original product (attributes, relationships) and replace the content of my controller with the new Product. This wasn't hard and appears to work nicely, although there may be (hopefully) a better way.

However, when I'm editing a Product, I have run into a serious issue and the above solution does not work. The Product model is now in the error state and I can not find any way to get a copy of this Product that isn't also in the same state.

What I cant' figure out is what I can do with this model once it hits the error state. I have tried the following:

Rollback: This doesn't work. You can't rollback a transaction in the error state.

Reload: Same as above. Not allowed to reload a record in the error state.

Grab a new copy of the record: So I try App.Product.find(id) with the same id as the existing record. It just gives me a copy of the existing record, in the error state.

I'm hoping I'm missing something fairly basic here. Is it possible to roll a record nicely out of an error state (or invalid state for that matter)?

If there is a simple way to change the state of these models, should we still be creating a new transaction for further attempts to commit?

Upvotes: 21

Views: 3861

Answers (4)

stevekane
stevekane

Reputation: 372

You could try creating a parallel representation of the model as an Ember.Object that is not persisted but has the same properties as your persisted model. If your ajax bounces back in an error state you can use the error callback provided by the ajax method to do something.

In this case, the "something" might be to delete the record, and then clone the properties from your dummy object into a new record and re-save the record. On a success callback simply destroy your temp object and if all records are clean then clear your temp objects (to prevent lingering temp objects).

This could also be insane... but it strikes me as an option.

Upvotes: 0

jsmecham
jsmecham

Reputation: 83

With the addition of DS.Errors in 1.0.0-beta5 (see https://github.com/emberjs/data/commit/994f3b234ef899b79138ddece60d8b214c5449e3) you should be able to call...

record.get("errors").clear();

This will clear out the previous errors and triggers becameValid.

Upvotes: 8

David Monagle
David Monagle

Reputation: 1801

So after a few days of reading source and experimenting, I have come to the conclusion that this is functionality that is not yet implemented. To move a record into another state you are supposed to send an event to it which passes it on the statemanager. There appears to be no events registered on the error state that allows us to recover the record.

There is an ugly workaround - I can call transitionTo on the statemanager of the record and force it into the state we want. I did not decide to do this lightly, but at this point I must continue on with the project while I wait for ember-data to evolve. So if the record is so far unsaved, we can rescue it from an invalid or error state by calling:

model.get('stateManager').transitionTo('loaded.created.uncommitted')

or for an existing record:

model.get('stateManager').transitionTo('loaded.updated')

Once this has been called, you can attempt to call commit again on the transaction that the model resides in. This will be the default transaction as the behaviour of ember-data is to move a model into the default transaction once commit has been called on it's original transaction. You can always retrieve the current transaction for a model by calling model.get('transaction')

So at the end of this, I have a way to create the typical CRUD scenario that we might see in Ruby on Rails, but I don't believe this is the ideal way to do it. I do believe however that at this point in time, neither does the ember-data team.

For those of you interested in having CRUD functionality as controller and route mixins for Ember, I have a Gist that contains the code I cam currently using. This is working fine, recovers from save errors as well as validation errors. Hopefully I can continue to refine this as ember-data evolves.

Upvotes: 14

Shimon Rachlenko
Shimon Rachlenko

Reputation: 5517

You can trigger a becameValid event on it:

record.send("becameValid");

This should transition the model to uncommitted state.

Upvotes: 2

Related Questions