-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
154 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
require 'test_helper' | ||
|
||
module ActiveModel | ||
class Serializer | ||
class Adapter | ||
class JsonApi | ||
class ErrorsTest < Minitest::Test | ||
|
||
# see | ||
# https://github.com/rails/rails/blob/4-2-stable/activemodel/lib/active_model/errors.rb | ||
# The below allows you to do: | ||
# | ||
# model = ModelWithErrors.new | ||
# model.validate! # => ["cannot be nil"] | ||
# model.errors.full_messages # => ["name cannot be nil"] | ||
class ModelWithErrors | ||
# Required dependency for ActiveModel::Errors | ||
extend ActiveModel::Naming | ||
def initialize | ||
@errors = ActiveModel::Errors.new(self) | ||
end | ||
attr_accessor :name | ||
attr_reader :errors | ||
|
||
# The following methods are needed to be minimally implemented | ||
|
||
def read_attribute_for_validation(attr) | ||
send(attr) | ||
end | ||
|
||
def self.human_attribute_name(attr, options = {}) | ||
attr | ||
end | ||
|
||
def self.lookup_ancestors | ||
[self] | ||
end | ||
end | ||
|
||
def setup | ||
@model = ModelWithErrors.new | ||
end | ||
|
||
class JsonApiErrorSerializer < ActiveModel::Serializer | ||
attribute :source | ||
attribute :detail | ||
|
||
def source | ||
{pointer: "data/attributes/#{object.first}"} | ||
end | ||
|
||
def detail | ||
detail = object.last | ||
if detail.respond_to?(:join) | ||
detail.join | ||
else | ||
detail | ||
end | ||
end | ||
end | ||
|
||
class JsonApiErrorsSerializer < ActiveModel::Serializer | ||
has_many :errors, serializer: JsonApiErrorSerializer | ||
|
||
def errors | ||
object.messages.to_a | ||
end | ||
end | ||
|
||
class ActiveModel::Serializer::Adapter::JsonApiError < ActiveModel::Serializer::Adapter::FlattenJson | ||
end | ||
|
||
def test_active_model_errors | ||
@model.errors.add(:name, "cannot be nil") | ||
serializer_opts = {serializer: JsonApiErrorSerializer} | ||
errors = @model.errors | ||
|
||
serializer = JsonApiErrorSerializer.new(errors.first, serializer_opts) | ||
expected_error_object = | ||
{ | ||
source: { pointer: 'data/attributes/name' }, | ||
detail: 'cannot be nil' | ||
} | ||
assert_equal serializer.attributes, expected_error_object | ||
|
||
serializer = JsonApiErrorsSerializer.new(errors, serializer_opts) | ||
adapter_class = ActiveModel::Serializer::Adapter::JsonApiError | ||
adapter_opts = { adapter: :json_api_error } | ||
|
||
adapter = ActiveModel::Serializer::Adapter.create(serializer, adapter_opts) | ||
expected_error_response = { errors: [expected_error_object] } | ||
assert_equal adapter.as_json, expected_error_response | ||
end | ||
=begin | ||
## http://jsonapi.org/format/#document-top-level | ||
A document MUST contain at least one of the following top-level members: | ||
- data: the document's "primary data" | ||
- errors: an array of error objects | ||
- meta: a meta object that contains non-standard meta-information. | ||
The members data and errors MUST NOT coexist in the same document. | ||
## http://jsonapi.org/format/#error-objects | ||
Error objects provide additional information about problems encountered while performing an operation. Error objects MUST be returned as an array keyed by errors in the top level of a JSON API document. | ||
An error object MAY have the following members: | ||
- id: a unique identifier for this particular occurrence of the problem. | ||
- links: a links object containing the following members: | ||
- about: a link that leads to further details about this particular occurrence of the problem. | ||
- status: the HTTP status code applicable to this problem, expressed as a string value. | ||
- code: an application-specific error code, expressed as a string value. | ||
- title: a short, human-readable summary of the problem that SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization. | ||
- detail: a human-readable explanation specific to this occurrence of the problem. | ||
- source: an object containing references to the source of the error, optionally including any of the following members: | ||
- pointer: a JSON Pointer [RFC6901] to the associated entity in the request document [e.g. "/data" for a primary data object, or "/data/attributes/title" for a specific attribute]. | ||
- parameter: a string indicating which query parameter caused the error. | ||
- meta: a meta object containing non-standard meta-information about the error. | ||
## http://emberjs.com/blog/2015/06/18/ember-data-1-13-released.html#toc_using-json-api-error-object-format | ||
Starting with Ember Data 1.13 we are using JSON API format to communicate errors from | ||
the adapter to the store. | ||
We are deprecating the current Ruby on Rails inspired format for creating | ||
InvalidError objects and replacing it with proper JSON API objects. The old | ||
format is supported with a deprecation warning in 1.13. | ||
Deprecated format: | ||
```js | ||
new DS.InvalidError({ | ||
first_name: ['is invalid'] | ||
}); | ||
``` | ||
New format: | ||
```js | ||
new DS.InvalidError([ | ||
{ | ||
source: { pointer: 'data/attributes/first_name' }, | ||
detail: 'is invalid' | ||
} | ||
]); | ||
=end | ||
end | ||
end | ||
end | ||
end | ||
end |