RFC: Json Api Errors (WIP)

- ActiveModelSerializers::JsonPointer
- ActiveModel::Serializer::Adapter::JsonApi::Error
- ActiveModel::Serializer::Adapter::JsonApi::Error.attributes
- Fix rubocop config
This commit is contained in:
Benjamin Fleischer
2015-07-14 00:29:15 -05:00
parent df815c48ba
commit 0ba944dabf
16 changed files with 329 additions and 2 deletions

View File

@@ -0,0 +1,41 @@
require 'test_helper'
module ActionController
module Serialization
class JsonApi
class ErrorsTest < ActionController::TestCase
def test_active_model_with_multiple_errors
get :render_resource_with_errors
expected_errors_object =
{ 'errors'.freeze =>
[
{ :source => { :pointer => '/data/attributes/name' }, :detail => 'cannot be nil' },
{ :source => { :pointer => '/data/attributes/name' }, :detail => 'must be longer' },
{ :source => { :pointer => '/data/attributes/id' }, :detail => 'must be a uuid' }
]
}.to_json
assert_equal json_reponse_body.to_json, expected_errors_object
end
def json_reponse_body
JSON.load(@response.body)
end
class ErrorsTestController < ActionController::Base
def render_resource_with_errors
resource = Profile.new(name: 'Name 1',
description: 'Description 1',
comments: 'Comments 1')
resource.errors.add(:name, 'cannot be nil')
resource.errors.add(:name, 'must be longer')
resource.errors.add(:id, 'must be a uuid')
render json: resource, adapter: :json_api
end
end
tests ErrorsTestController
end
end
end
end

View File

@@ -102,7 +102,8 @@ module ActiveModelSerializers
'null'.freeze => ActiveModelSerializers::Adapter::Null,
'json'.freeze => ActiveModelSerializers::Adapter::Json,
'attributes'.freeze => ActiveModelSerializers::Adapter::Attributes,
'json_api'.freeze => ActiveModelSerializers::Adapter::JsonApi
'json_api'.freeze => ActiveModelSerializers::Adapter::JsonApi,
'json_api/error'.freeze => ActiveModelSerializers::Adapter::JsonApi::Error
}
actual = ActiveModelSerializers::Adapter.adapter_map
assert_equal actual, expected_adapter_map
@@ -113,6 +114,7 @@ module ActiveModelSerializers
'attributes'.freeze,
'json'.freeze,
'json_api'.freeze,
'json_api/error'.freeze,
'null'.freeze
]
end

View File

@@ -0,0 +1,20 @@
require 'test_helper'
class ActiveModelSerializers::JsonPointerTest < ActiveSupport::TestCase
def test_attribute_pointer
attribute_name = 'title'
pointer = ActiveModelSerializers::JsonPointer.new(:attribute, attribute_name)
assert_equal '/data/attributes/title', pointer
end
def test_primary_data_pointer
pointer = ActiveModelSerializers::JsonPointer.new(:primary_data)
assert_equal '/data', pointer
end
def test_unkown_data_pointer
assert_raises(TypeError) do
ActiveModelSerializers::JsonPointer.new(:unknown)
end
end
end

View File

@@ -0,0 +1,64 @@
require 'test_helper'
module ActiveModelSerializers
module Adapter
class JsonApi < Base
class ErrorsTest < Minitest::Test
include ActiveModel::Serializer::Lint::Tests
def setup
@resource = ModelWithErrors.new
end
def test_active_model_with_error
options = {
serializer: ActiveModel::Serializer::ErrorSerializer,
adapter: :'json_api/error'
}
@resource.errors.add(:name, 'cannot be nil')
serializable_resource = ActiveModel::SerializableResource.new(@resource, options)
assert_equal serializable_resource.serializer_instance.attributes, {}
assert_equal serializable_resource.serializer_instance.object, @resource
expected_errors_object =
{ 'errors'.freeze =>
[
{
source: { pointer: '/data/attributes/name' },
detail: 'cannot be nil'
}
]
}
assert_equal serializable_resource.as_json, expected_errors_object
end
def test_active_model_with_multiple_errors
options = {
serializer: ActiveModel::Serializer::ErrorSerializer,
adapter: :'json_api/error'
}
@resource.errors.add(:name, 'cannot be nil')
@resource.errors.add(:name, 'must be longer')
@resource.errors.add(:id, 'must be a uuid')
serializable_resource = ActiveModel::SerializableResource.new(@resource, options)
assert_equal serializable_resource.serializer_instance.attributes, {}
assert_equal serializable_resource.serializer_instance.object, @resource
expected_errors_object =
{ 'errors'.freeze =>
[
{ :source => { :pointer => '/data/attributes/name' }, :detail => 'cannot be nil' },
{ :source => { :pointer => '/data/attributes/name' }, :detail => 'must be longer' },
{ :source => { :pointer => '/data/attributes/id' }, :detail => 'must be a uuid' }
]
}
assert_equal serializable_resource.as_json, expected_errors_object
end
end
end
end
end

11
test/fixtures/poro.rb vendored
View File

@@ -27,6 +27,17 @@ class Model < ActiveModelSerializers::Model
end
end
# 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 < ::ActiveModelSerializers::Model
attr_accessor :name
end
class Profile < Model
end

View File

@@ -27,6 +27,15 @@ module ActiveModel
def updated_at
end
def errors
end
def self.human_attribute_name(attr, options = {})
end
def self.lookup_ancestors
end
def self.model_name
@_model_name ||= ActiveModel::Name.new(self)
end

View File

@@ -31,5 +31,37 @@ module ActiveModel
def test_use_adapter_with_adapter_option_as_false
refute ActiveModel::SerializableResource.new(@resource, { adapter: false }).use_adapter?
end
class SerializableResourceErrorsTest < Minitest::Test
def test_serializable_resource_with_errors
options = nil
resource = ModelWithErrors.new
resource.errors.add(:name, 'must be awesome')
serializable_resource = ActiveModel::SerializableResource.new(resource)
expected_response_document =
{ 'errors'.freeze =>
[
{ :source => { :pointer => '/data/attributes/name' }, :detail => 'must be awesome' }
]
}
assert_equal serializable_resource.as_json(options), expected_response_document
end
def test_serializable_resource_with_collection_containing_errors
options = nil
resources = []
resources << resource = ModelWithErrors.new
resource.errors.add(:title, 'must be amazing')
resources << ModelWithErrors.new
serializable_resource = ActiveModel::SerializableResource.new(resources)
expected_response_document =
{ 'errors'.freeze =>
[
{ :source => { :pointer => '/data/attributes/title' }, :detail => 'must be amazing' }
]
}
assert_equal serializable_resource.as_json(options), expected_response_document
end
end
end
end