Suffix

Published by Simon Schoeters

Error handling with Ember Data

I am building a small Ember app for a friend, it's my first real Ember app and there is still a lot to learn. Showing validation errors when saving an Ember Data model for example, something that took me far longer as it should have.

In Ember you can automagically access validation errors returned by the backend in your templates. DS.Errors handles everything for you, but, documentation is sparse and every piece has to be just right for it to work.

Server response

Ember Data expects the server to respond in a certain way. The JSON response containing the error messages should include a root element with child nodes for each error. The error elements contain arrays with the error messages:

{
  "errors": {
    "email": ["can't be blank"]
  }
}

Note that Ruby on Rails does not include the errors root element by default so make sure to add it:

render json: { errors: post.errors }, status: 422

Set your response HTTP status code as well. I was responding with a 400 “Bad Request” but Ember Data only processes the error messages when it sees a 422 “Unprocessable Entity”, which is the correct status code by the way.

ActiveModelAdapter

I was using the RESTAdapter which doesn't include the error mapping magic out of the box. Use the ActiveModelAdapter with the ActiveModel::Serializers Ruby gem to make it work seamlessly or add this snippet to your adapter definition if you need the RESTAdapter for some reason.

Saving the model

Make sure to handle errors when saving your model:
post.save().then(function() {
  console.log("Post saved.");
}, function(response) {
  console.error("Post not saved!");
});

A simple post.save() without promises will throw an error and stop the script execution.

Uncaught Error: Assertion Failed: Error: The backend rejected the commit because it was invalid: {...}

Template

Finally your DS.Error object should contain all the error messages as attributes so you can access them individually.

{{#each error in errors.email}}
  {{error.message}}
{{/each}}

This post by Marc Qualie was extremely helpful to get me on the right track, thank you Marc!