How should errors be handled when using the Ember.js Data RESTAdapter?

This weekend I was trying to figure the same thing out. Going off what Luke said, I took a closer look at the ember-data source for the latest commit (Dec 11).

TLDR; to handle ember-data update/create errors, simply define becameError() and becameInvalid(errors) on your DS.Model instance. The cascade triggered by the RESTadapter’s AJAX error callback will eventually call these functions you define.

Example:

App.Post = DS.Model.extend
  title: DS.attr "string"
  body: DS.attr "string"

  becameError: ->
    # handle error case here
    alert 'there was an error!'

  becameInvalid: (errors) ->
    # record was invalid
    alert "Record was invalid because: #{errors}"

Here’s the full walk through the source:

In the REST adapter, the AJAX callback error function is given here:

   this.ajax(this.buildURL(root, id), "PUT", {
      data: data,
      context: this,
      success: function(json) {
        Ember.run(this, function(){
          this.didUpdateRecord(store, type, record, json);
        });
      },
      error: function(xhr) {
        this.didError(store, type, record, xhr);
      }
    });

didError is defined here and it in turn calls the store’s recordWasInvalid or recordWasError depending on the response:

  didError: function(store, type, record, xhr) {
    if (xhr.status === 422) {
      var data = JSON.parse(xhr.responseText);
      store.recordWasInvalid(record, data['errors']);
    } else {
      store.recordWasError(record);
    }
  },

In turn, store.recordWasInvalid and store.recordWasError (defined here) call the record (a DS.Model)’s handlers. In the invalid case, it passes along error messages from the adapter as an argument.

 recordWasInvalid: function(record, errors) {
    record.adapterDidInvalidate(errors);
  },

  recordWasError: function(record) {
    record.adapterDidError();
  },

DS.Model.adapterDidInvalidate and adapterDidError (defined here) simply send('becameInvalid', errors) or send('becameError') which finally leads us to the handlers here:

  didLoad: Ember.K,
  didUpdate: Ember.K,
  didCreate: Ember.K,
  didDelete: Ember.K,
  becameInvalid: Ember.K,
  becameError: Ember.K,

(Ember.K is just a dummy function for returning this. See here)

So, the conclusion is, you simply need to define functions for becameInvalid and becameError on your model to handle these cases.

Hope this helps someone else; the docs certainly don’t reflect this right now.

Leave a Comment