Deleting model from store after save failure


#1

I am using the ActiveModelAdapter to store models in our Rails backend. When the save fails, I’d like to remove it from the store. I tried verious different variantes, but none worked so far.

My base code snippet looks like this:

  c = @store.createRecord('commission',
    {
      amount:         -parseFloat(App.normalizeAmount(@get('withdrawalAmount'))),
      commissionType: 'withdrawal'
    }
  )
  c.save().then(->
    Us.showSuccess(App.t('statement.withdrawal.booked'))
  ).catch(->
    Us.showError(App.t('statement.withdrawal.booking_failed'))
    c.deleteRecord()
  )

Unfortunately, c.deleteRecord() raises an assertion error:

Assertion Failed: Error: Attempted to handle event `deleteRecord` on <App.Commission:ember1008:null> while in state root.loaded.created.inFlight.  

Instead of c.deleteRecord() I tried @store.deleteRecord(c), which raises the same assertion error. I also tried c.rollback(), which has no effect.

Any ideas how to get rid of the erratic record?

Ember Data : 1.0.0-beta.7+canary.ab589b32 

#2

try to use rollback()

c.save().then(->
    Us.showSuccess(App.t('statement.withdrawal.booked'))
  ).catch(->
    Us.showError(App.t('statement.withdrawal.booking_failed'))
    c.rollback();
  )

#3

I tried calling rollback(), but the record is still in the store afterwards.


#4

You need to call unloadRecord() after calling rollback(). It is a two step process in that you can’t unload dirty records from the store nor can you unload records that are in the process of being deleted (otherwise known as being ‘inflight’).



#5

Unfortunately, that also yields an assertion error:

Assertion Failed: Error: Assertion Failed: You can only unload a record which is not inFlight. `<App.Commission:ember825:null> ` 

Code:

  c = @store.createRecord('commission',
    {
      amount:         -parseFloat(App.normalizeAmount(@get('withdrawalAmount'))),
      commissionType: 'withdrawal'
    }
  )
  c.save().then(->
    Us.showSuccess(App.t('statement.withdrawal.booked'))
  ).catch(->
    Us.showError(App.t('statement.withdrawal.booking_failed'))
    c.rollback()
    c.unloadRecord()
  )

#6

Looks like you got back a 422 response, which right now leaves the record in an ‘inFlight’ state (see https://github.com/emberjs/data/issues/1632 and https://github.com/emberjs/data/issues/1764). My workaround when getting a 422 response was to call record.transitionTo(‘created.uncommitted’). From there you should be able to delete the record. I’m guessing this will change in a future release of Ember Data since there’s been some discussion around it.


#7

Thanks, that worked. It only works for 422 status codes, though. For 400, no workaround is necessary and applying the transitionTo('created.uncommitted') workaround raises another error. sigh

Any recommendations for a robust solution? For the time being, I’ll resort to just returning a 400 status from the backend…


#8

Unfortunately, I don’t. I’m somewhat new to Ember Data myself. I was hoping somebody more knowledgable and experienced would weigh in with an opinion. From what I saw in this - http://reefpoints.dockyard.com/2014/04/29/the-problem-with-server-rendered-errors.html - handling server side errors can be a thorny problem to generalize.

Update: I would read Ember Data, ActiveModelAdapter, and Validations for further discussion on the topic.


#9

hi @thiloginkel, i ran into the same kind of frustration today. The following workarround works for me at the moment:

    var model = this.get('model');
    var store = model.store;

    model.deleteRecord();
    model.save().catch(function(err){
      model.transitionTo('loaded.saved');
      var payload = model.serialize({includeId: true});
      store.unloadRecord(model)
      store.pushPayload('nestedSet',{nested_set:payload});
    });

Happy if anyone has a better solution for this :smiley:


#10

Worked for me! Thanks @jens!


#11

I actually only needed to add the loaded.saved line:

  record.destroyRecord().finally(() => {
    // this bug should be fixed in future version of ember data (https://github.com/emberjs/data/issues/1632)
    // fix from https://discuss.emberjs.com/t/deleting-model-from-store-after-save-failure/5072/8
    record.transitionTo('loaded.saved');
    record.unloadRecord();
  });

I’m using ember 2.13