fun_with_json_api 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +4 -1
- data/config/locales/fun_with_json_api.en.yml +29 -2
- data/lib/fun_with_json_api.rb +30 -2
- data/lib/fun_with_json_api/action_controller_extensions/serialization.rb +18 -0
- data/lib/fun_with_json_api/attribute.rb +3 -3
- data/lib/fun_with_json_api/attributes/relationship.rb +37 -23
- data/lib/fun_with_json_api/attributes/relationship_collection.rb +55 -38
- data/lib/fun_with_json_api/attributes/string_attribute.rb +12 -1
- data/lib/fun_with_json_api/attributes/uuid_v4_attribute.rb +27 -0
- data/lib/fun_with_json_api/controller_methods.rb +1 -1
- data/lib/fun_with_json_api/deserializer.rb +61 -8
- data/lib/fun_with_json_api/deserializer_class_methods.rb +37 -7
- data/lib/fun_with_json_api/exceptions/illegal_client_generated_identifier.rb +17 -0
- data/lib/fun_with_json_api/exceptions/invalid_client_generated_identifier.rb +17 -0
- data/lib/fun_with_json_api/exceptions/invalid_document_identifier.rb +17 -0
- data/lib/fun_with_json_api/exceptions/invalid_document_type.rb +20 -0
- data/lib/fun_with_json_api/exceptions/invalid_relationship.rb +5 -3
- data/lib/fun_with_json_api/exceptions/invalid_relationship_type.rb +17 -0
- data/lib/fun_with_json_api/exceptions/missing_resource.rb +15 -0
- data/lib/fun_with_json_api/exceptions/unknown_attribute.rb +15 -0
- data/lib/fun_with_json_api/exceptions/unknown_relationship.rb +15 -0
- data/lib/fun_with_json_api/find_collection_from_document.rb +124 -0
- data/lib/fun_with_json_api/find_resource_from_document.rb +112 -0
- data/lib/fun_with_json_api/pre_deserializer.rb +1 -0
- data/lib/fun_with_json_api/railtie.rb +30 -1
- data/lib/fun_with_json_api/schema_validator.rb +47 -0
- data/lib/fun_with_json_api/schema_validators/check_attributes.rb +52 -0
- data/lib/fun_with_json_api/schema_validators/check_document_id_matches_resource.rb +96 -0
- data/lib/fun_with_json_api/schema_validators/check_document_type_matches_resource.rb +40 -0
- data/lib/fun_with_json_api/schema_validators/check_relationships.rb +127 -0
- data/lib/fun_with_json_api/version.rb +1 -1
- data/spec/dummy/log/test.log +172695 -0
- data/spec/fixtures/active_record.rb +6 -0
- data/spec/fun_with_json_api/controller_methods_spec.rb +8 -3
- data/spec/fun_with_json_api/deserializer_class_methods_spec.rb +14 -6
- data/spec/fun_with_json_api/deserializer_spec.rb +155 -40
- data/spec/fun_with_json_api/exception_spec.rb +9 -9
- data/spec/fun_with_json_api/find_collection_from_document_spec.rb +203 -0
- data/spec/fun_with_json_api/find_resource_from_document_spec.rb +100 -0
- data/spec/fun_with_json_api/pre_deserializer_spec.rb +26 -26
- data/spec/fun_with_json_api/railtie_spec.rb +88 -0
- data/spec/fun_with_json_api/schema_validator_spec.rb +94 -0
- data/spec/fun_with_json_api/schema_validators/check_attributes_spec.rb +52 -0
- data/spec/fun_with_json_api/schema_validators/check_document_id_matches_resource_spec.rb +115 -0
- data/spec/fun_with_json_api/schema_validators/check_document_type_matches_resource_spec.rb +30 -0
- data/spec/fun_with_json_api/schema_validators/check_relationships_spec.rb +150 -0
- data/spec/fun_with_json_api_spec.rb +148 -4
- metadata +49 -4
- data/spec/example_spec.rb +0 -64
@@ -3,7 +3,7 @@ require 'fun_with_json_api/exception_serializer'
|
|
3
3
|
module FunWithJsonApi
|
4
4
|
module ControllerMethods
|
5
5
|
def render_fun_with_json_api_exception(exception)
|
6
|
-
render
|
6
|
+
render json_api: exception,
|
7
7
|
serializer: FunWithJsonApi::ExceptionSerializer,
|
8
8
|
adapter: :json,
|
9
9
|
status: exception.http_status
|
@@ -19,14 +19,28 @@ module FunWithJsonApi
|
|
19
19
|
attr_reader :resource_class
|
20
20
|
|
21
21
|
attr_reader :attributes
|
22
|
-
attr_reader :relationships
|
23
22
|
|
24
23
|
def initialize(options = {})
|
25
24
|
@id_param = options.fetch(:id_param) { self.class.id_param }
|
26
|
-
@type = options
|
25
|
+
@type = options.fetch(:type) { self.class.type }
|
27
26
|
@resource_class = options[:resource_class]
|
28
|
-
@
|
29
|
-
|
27
|
+
@resource_collection = options[:resource_collection] if @type
|
28
|
+
load_attributes_from_options(options)
|
29
|
+
load_relationships_from_options(options)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Loads a collection of of `resource_class` instances with `id_param` matching `id_values`
|
33
|
+
def load_collection_from_id_values(id_values)
|
34
|
+
resource_collection.where(id_param => id_values)
|
35
|
+
end
|
36
|
+
|
37
|
+
def format_collection_ids(collection)
|
38
|
+
collection.map { |resource| resource.public_send(id_param).to_s }
|
39
|
+
end
|
40
|
+
|
41
|
+
# Loads a single instance of `resource_class` with a `id_param` matching `id_value`
|
42
|
+
def load_resource_from_id_value(id_value)
|
43
|
+
resource_collection.find_by(id_param => id_value)
|
30
44
|
end
|
31
45
|
|
32
46
|
# Takes a parsed params hash from ActiveModelSerializers::Deserialization and sanitizes values
|
@@ -37,16 +51,47 @@ module FunWithJsonApi
|
|
37
51
|
]
|
38
52
|
end
|
39
53
|
|
40
|
-
def type
|
41
|
-
@type ||= self.class.type
|
42
|
-
end
|
43
|
-
|
44
54
|
def resource_class
|
45
55
|
@resource_class ||= self.class.resource_class
|
46
56
|
end
|
47
57
|
|
58
|
+
def resource_collection
|
59
|
+
@resource_collection ||= resource_class
|
60
|
+
end
|
61
|
+
|
62
|
+
def relationships
|
63
|
+
relationship_lookup.values
|
64
|
+
end
|
65
|
+
|
66
|
+
def relationship_for(resource_name)
|
67
|
+
relationship_lookup.fetch(resource_name)
|
68
|
+
end
|
69
|
+
|
48
70
|
private
|
49
71
|
|
72
|
+
attr_reader :relationship_lookup
|
73
|
+
|
74
|
+
def load_attributes_from_options(options)
|
75
|
+
@attributes = filter_attributes_by_name(options[:attributes], self.class.attributes)
|
76
|
+
end
|
77
|
+
|
78
|
+
def load_relationships_from_options(options = {})
|
79
|
+
options_config = {}
|
80
|
+
|
81
|
+
# Filter resources and build an options hash for each
|
82
|
+
filter_relationships_by_name(
|
83
|
+
options[:relationships], self.class.relationship_names
|
84
|
+
).each do |relationship|
|
85
|
+
options_config[relationship] = options.fetch(relationship, {})
|
86
|
+
end
|
87
|
+
|
88
|
+
# Build the relationships and store them into a lookup hash
|
89
|
+
@relationship_lookup = {}
|
90
|
+
self.class.build_relationships(options_config).each do |relationship|
|
91
|
+
@relationship_lookup[relationship.name] = relationship
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
50
95
|
def filter_attributes_by_name(attribute_names, attributes)
|
51
96
|
if attribute_names
|
52
97
|
attributes.keep_if { |attribute| attribute_names.include?(attribute.name) }
|
@@ -55,6 +100,14 @@ module FunWithJsonApi
|
|
55
100
|
end
|
56
101
|
end
|
57
102
|
|
103
|
+
def filter_relationships_by_name(relationship_names, relationships)
|
104
|
+
if relationship_names
|
105
|
+
relationships.keep_if { |relationship| relationship_names.include?(relationship) }
|
106
|
+
else
|
107
|
+
relationships
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
58
111
|
# Calls <attribute.as> on the current instance, override the #<as> method to change loading
|
59
112
|
def serialize_attribute_values(attributes, params)
|
60
113
|
attributes.select { |attribute| params.key?(attribute.param_value) }
|
@@ -3,9 +3,13 @@ require 'fun_with_json_api/attribute'
|
|
3
3
|
module FunWithJsonApi
|
4
4
|
# Provides a basic DSL for defining a FunWithJsonApi::Deserializer
|
5
5
|
module DeserializerClassMethods
|
6
|
-
def id_param(id_param = nil)
|
7
|
-
@id_param = id_param if id_param
|
8
|
-
@id_param || :id
|
6
|
+
def id_param(id_param = nil, format: false)
|
7
|
+
@id_param = id_param.to_sym if id_param
|
8
|
+
(@id_param || :id).tap do |param|
|
9
|
+
if format
|
10
|
+
attribute(:id, as: param, format: format) # Create a new id attribute
|
11
|
+
end
|
12
|
+
end
|
9
13
|
end
|
10
14
|
|
11
15
|
def type(type = nil)
|
@@ -39,7 +43,7 @@ module FunWithJsonApi
|
|
39
43
|
deserializer_class_or_callable,
|
40
44
|
options
|
41
45
|
).tap do |relationship|
|
42
|
-
|
46
|
+
add_parse_resource_method(relationship)
|
43
47
|
relationships << relationship
|
44
48
|
end
|
45
49
|
end
|
@@ -52,26 +56,52 @@ module FunWithJsonApi
|
|
52
56
|
deserializer_class_or_callable,
|
53
57
|
options
|
54
58
|
).tap do |relationship|
|
55
|
-
|
59
|
+
add_parse_resource_method(relationship)
|
56
60
|
relationships << relationship
|
57
61
|
end
|
58
62
|
end
|
59
63
|
|
60
64
|
# rubocop:enable Style/PredicateName
|
61
65
|
|
62
|
-
def
|
63
|
-
|
66
|
+
def relationship_names
|
67
|
+
relationships.map(&:name)
|
68
|
+
end
|
69
|
+
|
70
|
+
def build_relationships(options)
|
71
|
+
options.map do |name, relationship_options|
|
72
|
+
relationship = relationships.detect { |rel| rel.name == name }
|
73
|
+
relationship.class.create(
|
74
|
+
relationship.name,
|
75
|
+
relationship.deserializer_class,
|
76
|
+
relationship_options.reverse_merge(relationship.options)
|
77
|
+
)
|
78
|
+
end
|
64
79
|
end
|
65
80
|
|
66
81
|
private
|
67
82
|
|
83
|
+
def relationships
|
84
|
+
@relationships ||= []
|
85
|
+
end
|
86
|
+
|
68
87
|
def add_parse_attribute_method(attribute)
|
69
88
|
define_method(attribute.sanitize_attribute_method) do |param_value|
|
70
89
|
attribute.call(param_value)
|
71
90
|
end
|
72
91
|
end
|
73
92
|
|
93
|
+
def add_parse_resource_method(resource)
|
94
|
+
define_method(resource.sanitize_attribute_method) do |param_value|
|
95
|
+
relationship_for(resource.name).call(param_value)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
74
99
|
def type_from_class_name
|
100
|
+
if name.nil?
|
101
|
+
Rails.logger.warn 'Unable to determine type for anonymous Deserializer'
|
102
|
+
return nil
|
103
|
+
end
|
104
|
+
|
75
105
|
resource_class_name = name.demodulize.sub(/Deserializer/, '').underscore
|
76
106
|
if ActiveModelSerializers.config.jsonapi_resource_type == :singular
|
77
107
|
resource_class_name.singularize
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module FunWithJsonApi
|
2
|
+
module Exceptions
|
3
|
+
# A server MUST return 403 Forbidden in response to an unsupported request to create a resource
|
4
|
+
# with a client-generated ID.
|
5
|
+
class IllegalClientGeneratedIdentifier < FunWithJsonApi::Exception
|
6
|
+
EXCEPTION_CODE = 'illegal_client_generated_identifier'.freeze
|
7
|
+
|
8
|
+
def initialize(message, payload = ExceptionPayload.new)
|
9
|
+
payload.code ||= EXCEPTION_CODE
|
10
|
+
payload.title ||= I18n.t(EXCEPTION_CODE, scope: 'fun_with_json_api.exceptions')
|
11
|
+
payload.status ||= '403'
|
12
|
+
payload.pointer ||= '/data/id'
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module FunWithJsonApi
|
2
|
+
module Exceptions
|
3
|
+
# A server MUST return 409 Conflict when processing a POST request to create a resource with a
|
4
|
+
# client-generated ID that already exists.
|
5
|
+
class InvalidClientGeneratedIdentifier < FunWithJsonApi::Exception
|
6
|
+
EXCEPTION_CODE = 'invalid_client_generated_identifier'.freeze
|
7
|
+
|
8
|
+
def initialize(message, payload = ExceptionPayload.new)
|
9
|
+
payload.code ||= EXCEPTION_CODE
|
10
|
+
payload.title ||= I18n.t(EXCEPTION_CODE, scope: 'fun_with_json_api.exceptions')
|
11
|
+
payload.status ||= '409'
|
12
|
+
payload.pointer ||= '/data/id'
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module FunWithJsonApi
|
2
|
+
module Exceptions
|
3
|
+
# A server MUST return 409 Conflict when processing a PATCH request in which the resource
|
4
|
+
# object's type and id do not match the server's endpoint
|
5
|
+
class InvalidDocumentIdentifier < FunWithJsonApi::Exception
|
6
|
+
EXCEPTION_CODE = 'invalid_document_identifier'.freeze
|
7
|
+
|
8
|
+
def initialize(message, payload = ExceptionPayload.new)
|
9
|
+
payload.code ||= EXCEPTION_CODE
|
10
|
+
payload.title ||= I18n.t(EXCEPTION_CODE, scope: 'fun_with_json_api.exceptions')
|
11
|
+
payload.status ||= '409'
|
12
|
+
payload.pointer ||= '/data/id'
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module FunWithJsonApi
|
2
|
+
module Exceptions
|
3
|
+
# A server MUST return 409 Conflict when processing a POST request in which the resource
|
4
|
+
# object's type is not among the type(s) that constitute the collection represented by the
|
5
|
+
# endpoint.
|
6
|
+
class InvalidDocumentType < FunWithJsonApi::Exception
|
7
|
+
EXCEPTION_CODE = 'invalid_document_type'.freeze
|
8
|
+
|
9
|
+
def initialize(message, payload = ExceptionPayload.new)
|
10
|
+
payload = Array.wrap(payload).each do |invalid|
|
11
|
+
invalid.code ||= EXCEPTION_CODE
|
12
|
+
invalid.title ||= I18n.t(EXCEPTION_CODE, scope: 'fun_with_json_api.exceptions')
|
13
|
+
invalid.status ||= '409'
|
14
|
+
invalid.pointer ||= '/data/type'
|
15
|
+
end
|
16
|
+
super
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -3,9 +3,11 @@ module FunWithJsonApi
|
|
3
3
|
# Indicates a Supplied relationships value is not formatted correctly
|
4
4
|
class InvalidRelationship < FunWithJsonApi::Exception
|
5
5
|
def initialize(message, payload = ExceptionPayload.new)
|
6
|
-
payload.
|
7
|
-
|
8
|
-
|
6
|
+
Array.wrap(payload).each do |invalid|
|
7
|
+
invalid.code ||= 'invalid_relationship'
|
8
|
+
invalid.title ||= I18n.t(:invalid_relationship, scope: 'fun_with_json_api.exceptions')
|
9
|
+
invalid.status ||= '400'
|
10
|
+
end
|
9
11
|
super
|
10
12
|
end
|
11
13
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module FunWithJsonApi
|
2
|
+
module Exceptions
|
3
|
+
# Indicates a supplied relationships type does match expected values
|
4
|
+
class InvalidRelationshipType < FunWithJsonApi::Exception
|
5
|
+
ERROR_CODE = 'invalid_relationship_type'.freeze
|
6
|
+
|
7
|
+
def initialize(message, payload = ExceptionPayload.new)
|
8
|
+
Array.wrap(payload).each do |invalid|
|
9
|
+
invalid.code ||= ERROR_CODE
|
10
|
+
invalid.title ||= I18n.t(ERROR_CODE, scope: 'fun_with_json_api.exceptions')
|
11
|
+
invalid.status ||= '409'
|
12
|
+
end
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module FunWithJsonApi
|
2
|
+
module Exceptions
|
3
|
+
# Indicates a Resource or Collection item was not able to be found
|
4
|
+
class MissingResource < FunWithJsonApi::Exception
|
5
|
+
def initialize(message, payload = ExceptionPayload.new)
|
6
|
+
payload = Array.wrap(payload).each do |missing|
|
7
|
+
missing.code ||= 'missing_resource'
|
8
|
+
missing.title ||= I18n.t('missing_resource', scope: 'fun_with_json_api.exceptions')
|
9
|
+
missing.status ||= '404'
|
10
|
+
end
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module FunWithJsonApi
|
2
|
+
module Exceptions
|
3
|
+
# Indicates a supplied attribute value is unknown to the current deserializer
|
4
|
+
class UnknownAttribute < FunWithJsonApi::Exception
|
5
|
+
def initialize(message, payload = ExceptionPayload.new)
|
6
|
+
payload = Array.wrap(payload).each do |unknown|
|
7
|
+
unknown.code ||= 'unknown_attribute'
|
8
|
+
unknown.title ||= I18n.t(:unknown_attribute, scope: 'fun_with_json_api.exceptions')
|
9
|
+
unknown.status ||= '422'
|
10
|
+
end
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module FunWithJsonApi
|
2
|
+
module Exceptions
|
3
|
+
# Indicates a supplied relationship value is unknown to the current deserializer
|
4
|
+
class UnknownRelationship < FunWithJsonApi::Exception
|
5
|
+
def initialize(message, payload = ExceptionPayload.new)
|
6
|
+
payload = Array.wrap(payload).each do |unknown|
|
7
|
+
unknown.code ||= 'unknown_relationship'
|
8
|
+
unknown.title ||= I18n.t(:unknown_relationship, scope: 'fun_with_json_api.exceptions')
|
9
|
+
unknown.status ||= '422'
|
10
|
+
end
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module FunWithJsonApi
|
2
|
+
class FindCollectionFromDocument
|
3
|
+
def self.find(*args)
|
4
|
+
new(*args).find
|
5
|
+
end
|
6
|
+
|
7
|
+
private_class_method :new
|
8
|
+
|
9
|
+
attr_reader :api_document
|
10
|
+
attr_reader :deserializer
|
11
|
+
delegate :id_param, :id_param, :resource_class, to: :deserializer
|
12
|
+
|
13
|
+
def initialize(api_document, deserializer)
|
14
|
+
@api_document = api_document.deep_stringify_keys
|
15
|
+
@deserializer = deserializer
|
16
|
+
end
|
17
|
+
|
18
|
+
def find
|
19
|
+
raise build_invalid_document_error unless document_is_valid_collection?
|
20
|
+
|
21
|
+
# Skip the checks, no point running through them for an empty array
|
22
|
+
return [] if document_ids.empty?
|
23
|
+
|
24
|
+
# Ensure the document matches the expected resource
|
25
|
+
check_document_types_match_deserializer!
|
26
|
+
|
27
|
+
# Load resource from id value
|
28
|
+
deserializer.load_collection_from_id_values(document_ids).tap do |collection|
|
29
|
+
check_collection_contains_all_requested_resources!(collection)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def document_ids
|
34
|
+
@document_id ||= api_document['data'].map { |item| item['id'] }
|
35
|
+
end
|
36
|
+
|
37
|
+
def document_types
|
38
|
+
@document_type ||= api_document['data'].map { |item| item['type'] }.uniq
|
39
|
+
end
|
40
|
+
|
41
|
+
def resource_type
|
42
|
+
@resource_type ||= deserializer.type
|
43
|
+
end
|
44
|
+
|
45
|
+
def document_is_valid_collection?
|
46
|
+
api_document.key?('data') && api_document['data'].is_a?(Array)
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def check_collection_contains_all_requested_resources!(collection)
|
52
|
+
if collection.size != document_ids.size
|
53
|
+
collection_ids = deserializer.format_collection_ids(collection)
|
54
|
+
raise build_missing_resources_error(collection_ids)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def check_document_types_match_deserializer!
|
59
|
+
invalid_document_types = document_types.reject { |type| type == resource_type }
|
60
|
+
raise build_invalid_document_types_error if invalid_document_types.any?
|
61
|
+
end
|
62
|
+
|
63
|
+
def build_invalid_document_error
|
64
|
+
payload = ExceptionPayload.new
|
65
|
+
payload.pointer = '/data'
|
66
|
+
payload.detail = 'Expected data to be an Array of resources'
|
67
|
+
Exceptions::InvalidDocument.new(
|
68
|
+
"Expected root data element with an Array: #{api_document.inspect}",
|
69
|
+
payload
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
73
|
+
def build_invalid_document_types_error
|
74
|
+
message = 'Expected type for each item to match expected resource type'\
|
75
|
+
": '#{resource_type}'"
|
76
|
+
payload = api_document['data'].each_with_index.map do |data, index|
|
77
|
+
next if data['type'] == resource_type
|
78
|
+
ExceptionPayload.new(
|
79
|
+
pointer: "/data/#{index}/type",
|
80
|
+
detail: document_type_does_not_match_endpoint_message(data['type'])
|
81
|
+
)
|
82
|
+
end.reject(&:nil?)
|
83
|
+
Exceptions::InvalidDocumentType.new(message, payload)
|
84
|
+
end
|
85
|
+
|
86
|
+
def build_missing_resources_error(collection_ids)
|
87
|
+
payload = document_ids.each_with_index.map do |resource_id, index|
|
88
|
+
build_missing_resource_payload(collection_ids, resource_id, index)
|
89
|
+
end.reject(&:nil?)
|
90
|
+
|
91
|
+
missing_values = document_ids.reject { |value| collection_ids.include?(value.to_s) }
|
92
|
+
message = "Couldn't find #{resource_class} items with "\
|
93
|
+
"#{id_param} in #{missing_values.inspect}"
|
94
|
+
Exceptions::MissingResource.new(message, payload)
|
95
|
+
end
|
96
|
+
|
97
|
+
def build_missing_resource_payload(collection_ids, resource_id, index)
|
98
|
+
unless collection_ids.include?(resource_id)
|
99
|
+
ExceptionPayload.new(
|
100
|
+
pointer: "/data/#{index}/id",
|
101
|
+
detail: missing_resource_message(resource_id)
|
102
|
+
)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def document_type_does_not_match_endpoint_message(type)
|
107
|
+
I18n.t(
|
108
|
+
:invalid_document_type,
|
109
|
+
type: type,
|
110
|
+
resource: resource_type,
|
111
|
+
scope: 'fun_with_json_api.find_collection_from_document'
|
112
|
+
)
|
113
|
+
end
|
114
|
+
|
115
|
+
def missing_resource_message(resource_id)
|
116
|
+
I18n.t(
|
117
|
+
:missing_resource,
|
118
|
+
resource: resource_type,
|
119
|
+
resource_id: resource_id,
|
120
|
+
scope: 'fun_with_json_api.find_collection_from_document'
|
121
|
+
)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|