Skip to content

Commit

Permalink
Merge pull request #2933 from twokul/error
Browse files Browse the repository at this point in the history
Extracts InvalidError into a separate file and makes it a subclass of Ember.Error
  • Loading branch information
bmac committed Mar 25, 2015
2 parents abcb0f0 + 25246fe commit 9c26d02
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 92 deletions.
6 changes: 2 additions & 4 deletions packages/ember-data/lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@ import {
} from "ember-data/system/model";
import Model from "ember-data/system/model";
import Snapshot from "ember-data/system/snapshot";
import {
InvalidError,
Adapter
} from "ember-data/system/adapter";
import { Adapter } from "ember-data/system/adapter";
import Serializer from "ember-data/system/serializer";
import DebugAdapter from "ember-data/system/debug";
import {
Expand Down Expand Up @@ -74,6 +71,7 @@ import setupContainer from "ember-data/setup-container";

import ContainerProxy from "ember-data/system/container-proxy";
import Relationship from "ember-data/system/relationships/state/relationship";
import InvalidError from "ember-data/system/model/errors/invalid";

DS.Store = Store;
DS.PromiseArray = PromiseArray;
Expand Down
90 changes: 2 additions & 88 deletions packages/ember-data/lib/system/adapter.js
Original file line number Diff line number Diff line change
@@ -1,97 +1,11 @@
import InvalidError from "ember-data/system/model/errors/invalid";

/**
@module ember-data
*/

var get = Ember.get;

var errorProps = [
'description',
'fileName',
'lineNumber',
'message',
'name',
'number',
'stack'
];

/**
A `DS.InvalidError` is used by an adapter to signal the external API
was unable to process a request because the content was not
semantically correct or meaningful per the API. Usually this means a
record failed some form of server side validation. When a promise
from an adapter is rejected with a `DS.InvalidError` the record will
transition to the `invalid` state and the errors will be set to the
`errors` property on the record.
For Ember Data to correctly map errors to their corresponding
properties on the model, Ember Data expects each error to be
namespaced under a key that matches the property name. For example
if you had a Post model that looked like this.
```js
App.Post = DS.Model.extend({
title: DS.attr('string'),
content: DS.attr('string')
});
```
To show an error from the server related to the `title` and
`content` properties your adapter could return a promise that
rejects with a `DS.InvalidError` object that looks like this:
```js
App.PostAdapter = DS.RESTAdapter.extend({
updateRecord: function() {
// Fictional adapter that always rejects
return Ember.RSVP.reject(new DS.InvalidError({
title: ['Must be unique'],
content: ['Must not be blank'],
}));
}
});
```
Your backend may use different property names for your records the
store will attempt extract and normalize the errors using the
serializer's `extractErrors` method before the errors get added to
the the model. As a result, it is safe for the `InvalidError` to
wrap the error payload unaltered.
Example
```javascript
App.ApplicationAdapter = DS.RESTAdapter.extend({
ajaxError: function(jqXHR) {
var error = this._super(jqXHR);
// 422 is used by this fictional server to signal a validation error
if (jqXHR && jqXHR.status === 422) {
var jsonErrors = Ember.$.parseJSON(jqXHR.responseText);
return new DS.InvalidError(jsonErrors);
} else {
// The ajax request failed however it is not a result of this
// record being in an invalid state so we do not return a
// `InvalidError` object.
return error;
}
}
});
```
@class InvalidError
@namespace DS
*/
function InvalidError(errors) {
var tmp = Error.prototype.constructor.call(this, "The backend rejected the commit because it was invalid: " + Ember.inspect(errors));
this.errors = errors;

for (var i=0, l=errorProps.length; i<l; i++) {
this[errorProps[i]] = tmp[errorProps[i]];
}
}

InvalidError.prototype = Ember.create(Error.prototype);

/**
An adapter is an object that receives requests from a store and
translates them into the appropriate action to take against your
Expand Down
78 changes: 78 additions & 0 deletions packages/ember-data/lib/system/model/errors/invalid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
var create = Ember.create;
var EmberError = Ember.Error;

/**
A `DS.InvalidError` is used by an adapter to signal the external API
was unable to process a request because the content was not
semantically correct or meaningful per the API. Usually this means a
record failed some form of server side validation. When a promise
from an adapter is rejected with a `DS.InvalidError` the record will
transition to the `invalid` state and the errors will be set to the
`errors` property on the record.
For Ember Data to correctly map errors to their corresponding
properties on the model, Ember Data expects each error to be
namespaced under a key that matches the property name. For example
if you had a Post model that looked like this.
```js
App.Post = DS.Model.extend({
title: DS.attr('string'),
content: DS.attr('string')
});
```
To show an error from the server related to the `title` and
`content` properties your adapter could return a promise that
rejects with a `DS.InvalidError` object that looks like this:
```js
App.PostAdapter = DS.RESTAdapter.extend({
updateRecord: function() {
// Fictional adapter that always rejects
return Ember.RSVP.reject(new DS.InvalidError({
title: ['Must be unique'],
content: ['Must not be blank'],
}));
}
});
```
Your backend may use different property names for your records the
store will attempt extract and normalize the errors using the
serializer's `extractErrors` method before the errors get added to
the the model. As a result, it is safe for the `InvalidError` to
wrap the error payload unaltered.
Example
```javascript
App.ApplicationAdapter = DS.RESTAdapter.extend({
ajaxError: function(jqXHR) {
var error = this._super(jqXHR);
// 422 is used by this fictional server to signal a validation error
if (jqXHR && jqXHR.status === 422) {
var jsonErrors = Ember.$.parseJSON(jqXHR.responseText);
return new DS.InvalidError(jsonErrors);
} else {
// The ajax request failed however it is not a result of this
// record being in an invalid state so we do not return a
// `InvalidError` object.
return error;
}
}
});
```
@class InvalidError
@namespace DS
*/
function InvalidError(errors) {
EmberError.call(this, "The backend rejected the commit because it was invalid: " + Ember.inspect(errors));
this.errors = errors;
}

InvalidError.prototype = create(EmberError.prototype);

export default InvalidError;

0 comments on commit 9c26d02

Please sign in to comment.