fun_with_json_api 0.0.1
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +28 -0
- data/config/locales/fun_with_json_api.en.yml +13 -0
- data/lib/fun_with_json_api/attribute.rb +38 -0
- data/lib/fun_with_json_api/attributes/boolean_attribute.rb +24 -0
- data/lib/fun_with_json_api/attributes/date_attribute.rb +22 -0
- data/lib/fun_with_json_api/attributes/datetime_attribute.rb +20 -0
- data/lib/fun_with_json_api/attributes/decimal_attribute.rb +23 -0
- data/lib/fun_with_json_api/attributes/float_attribute.rb +20 -0
- data/lib/fun_with_json_api/attributes/integer_attribute.rb +20 -0
- data/lib/fun_with_json_api/attributes/relationship.rb +73 -0
- data/lib/fun_with_json_api/attributes/relationship_collection.rb +99 -0
- data/lib/fun_with_json_api/attributes/string_attribute.rb +9 -0
- data/lib/fun_with_json_api/controller_methods.rb +12 -0
- data/lib/fun_with_json_api/deserializer.rb +70 -0
- data/lib/fun_with_json_api/deserializer_class_methods.rb +83 -0
- data/lib/fun_with_json_api/deserializer_config_builder.rb +48 -0
- data/lib/fun_with_json_api/exception.rb +27 -0
- data/lib/fun_with_json_api/exception_payload.rb +29 -0
- data/lib/fun_with_json_api/exception_payload_serializer.rb +17 -0
- data/lib/fun_with_json_api/exception_serializer.rb +15 -0
- data/lib/fun_with_json_api/exceptions/invalid_attribute.rb +13 -0
- data/lib/fun_with_json_api/exceptions/invalid_document.rb +12 -0
- data/lib/fun_with_json_api/exceptions/invalid_relationship.rb +13 -0
- data/lib/fun_with_json_api/exceptions/missing_relationship.rb +15 -0
- data/lib/fun_with_json_api/pre_deserializer.rb +61 -0
- data/lib/fun_with_json_api/railtie.rb +11 -0
- data/lib/fun_with_json_api/version.rb +3 -0
- data/lib/fun_with_json_api.rb +24 -0
- data/lib/tasks/fun_with_json_api_tasks.rake +4 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +29 -0
- data/spec/dummy/config/application.rb +25 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +41 -0
- data/spec/dummy/config/environments/production.rb +80 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +9 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +56 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/log/test.log +37839 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/example_spec.rb +64 -0
- data/spec/fixtures/active_record.rb +65 -0
- data/spec/fun_with_json_api/controller_methods_spec.rb +123 -0
- data/spec/fun_with_json_api/deserializer_class_methods_spec.rb +52 -0
- data/spec/fun_with_json_api/deserializer_spec.rb +450 -0
- data/spec/fun_with_json_api/exception_spec.rb +77 -0
- data/spec/fun_with_json_api/pre_deserializer_spec.rb +287 -0
- data/spec/fun_with_json_api_spec.rb +55 -0
- data/spec/spec_helper.rb +33 -0
- metadata +275 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
require 'fun_with_json_api/attribute'
|
3
|
+
require 'fun_with_json_api/deserializer_class_methods'
|
4
|
+
|
5
|
+
module FunWithJsonApi
|
6
|
+
class Deserializer
|
7
|
+
extend FunWithJsonApi::DeserializerClassMethods
|
8
|
+
|
9
|
+
# Creates a new instance of a
|
10
|
+
def self.create(options = {})
|
11
|
+
new(options)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Use DeserializerClass.create to build new instances
|
15
|
+
private_class_method :new
|
16
|
+
|
17
|
+
attr_reader :id_param
|
18
|
+
attr_reader :type
|
19
|
+
attr_reader :resource_class
|
20
|
+
|
21
|
+
attr_reader :attributes
|
22
|
+
attr_reader :relationships
|
23
|
+
|
24
|
+
def initialize(options = {})
|
25
|
+
@id_param = options.fetch(:id_param) { self.class.id_param }
|
26
|
+
@type = options[:type]
|
27
|
+
@resource_class = options[:resource_class]
|
28
|
+
@attributes = filter_attributes_by_name(options[:attributes], self.class.attributes)
|
29
|
+
@relationships = filter_attributes_by_name(options[:relationships], self.class.relationships)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Takes a parsed params hash from ActiveModelSerializers::Deserialization and sanitizes values
|
33
|
+
def sanitize_params(params)
|
34
|
+
Hash[
|
35
|
+
serialize_attribute_values(attributes, params) +
|
36
|
+
serialize_attribute_values(relationships, params)
|
37
|
+
]
|
38
|
+
end
|
39
|
+
|
40
|
+
def type
|
41
|
+
@type ||= self.class.type
|
42
|
+
end
|
43
|
+
|
44
|
+
def resource_class
|
45
|
+
@resource_class ||= self.class.resource_class
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def filter_attributes_by_name(attribute_names, attributes)
|
51
|
+
if attribute_names
|
52
|
+
attributes.keep_if { |attribute| attribute_names.include?(attribute.name) }
|
53
|
+
else
|
54
|
+
attributes
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Calls <attribute.as> on the current instance, override the #<as> method to change loading
|
59
|
+
def serialize_attribute_values(attributes, params)
|
60
|
+
attributes.select { |attribute| params.key?(attribute.param_value) }
|
61
|
+
.map { |attribute| serialize_attribute(attribute, params) }
|
62
|
+
end
|
63
|
+
|
64
|
+
# Calls <attribute.as> on the current instance, override the #<as> method to change loading
|
65
|
+
def serialize_attribute(attribute, params)
|
66
|
+
raw_value = params.fetch(attribute.param_value)
|
67
|
+
[attribute.param_value, public_send(attribute.sanitize_attribute_method, raw_value)]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'fun_with_json_api/attribute'
|
2
|
+
|
3
|
+
module FunWithJsonApi
|
4
|
+
# Provides a basic DSL for defining a FunWithJsonApi::Deserializer
|
5
|
+
module DeserializerClassMethods
|
6
|
+
def id_param(id_param = nil)
|
7
|
+
@id_param = id_param if id_param
|
8
|
+
@id_param || :id
|
9
|
+
end
|
10
|
+
|
11
|
+
def type(type = nil)
|
12
|
+
@type = type if type
|
13
|
+
@type || type_from_class_name
|
14
|
+
end
|
15
|
+
|
16
|
+
def resource_class(resource_class = nil)
|
17
|
+
@resource_class = resource_class if resource_class
|
18
|
+
@resource_class || type_from_class_name.singularize.classify.constantize
|
19
|
+
end
|
20
|
+
|
21
|
+
# Attributes
|
22
|
+
|
23
|
+
def attribute(name, options = {})
|
24
|
+
Attribute.create(name, options).tap do |attribute|
|
25
|
+
add_parse_attribute_method(attribute)
|
26
|
+
attributes << attribute
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def attributes
|
31
|
+
@attributes ||= []
|
32
|
+
end
|
33
|
+
|
34
|
+
# Relationships
|
35
|
+
|
36
|
+
def belongs_to(name, deserializer_class_or_callable, options = {})
|
37
|
+
Attributes::Relationship.create(
|
38
|
+
name,
|
39
|
+
deserializer_class_or_callable,
|
40
|
+
options
|
41
|
+
).tap do |relationship|
|
42
|
+
add_parse_attribute_method(relationship)
|
43
|
+
relationships << relationship
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# rubocop:disable Style/PredicateName
|
48
|
+
|
49
|
+
def has_many(name, deserializer_class_or_callable, options = {})
|
50
|
+
Attributes::RelationshipCollection.create(
|
51
|
+
name,
|
52
|
+
deserializer_class_or_callable,
|
53
|
+
options
|
54
|
+
).tap do |relationship|
|
55
|
+
add_parse_attribute_method(relationship)
|
56
|
+
relationships << relationship
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# rubocop:enable Style/PredicateName
|
61
|
+
|
62
|
+
def relationships
|
63
|
+
@relationships ||= []
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def add_parse_attribute_method(attribute)
|
69
|
+
define_method(attribute.sanitize_attribute_method) do |param_value|
|
70
|
+
attribute.call(param_value)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def type_from_class_name
|
75
|
+
resource_class_name = name.demodulize.sub(/Deserializer/, '').underscore
|
76
|
+
if ActiveModelSerializers.config.jsonapi_resource_type == :singular
|
77
|
+
resource_class_name.singularize
|
78
|
+
else
|
79
|
+
resource_class_name.pluralize
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module FunWithJsonAPi
|
2
|
+
# Builds an options hash for ActiveModelSerializers::Deserialization.jsonapi_parse
|
3
|
+
class DeserializerConfigBuilder
|
4
|
+
def self.build(deserializer)
|
5
|
+
new(deserializer).build
|
6
|
+
end
|
7
|
+
|
8
|
+
private_class_method :new
|
9
|
+
|
10
|
+
attr_reader :deserializer
|
11
|
+
|
12
|
+
def initialize(deserializer)
|
13
|
+
@deserializer = deserializer
|
14
|
+
end
|
15
|
+
|
16
|
+
def build
|
17
|
+
{
|
18
|
+
only: build_only_values,
|
19
|
+
keys: build_keys_value
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
|
25
|
+
def build_only_values
|
26
|
+
attribute_only_values(deserializer.attributes) +
|
27
|
+
attribute_only_values(deserializer.relationships)
|
28
|
+
end
|
29
|
+
|
30
|
+
def build_keys_value
|
31
|
+
Hash[
|
32
|
+
attribute_key_values(deserializer.attributes) +
|
33
|
+
attribute_key_values(deserializer.relationships)
|
34
|
+
]
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def attribute_only_values(attributes_or_relationships)
|
40
|
+
attributes_or_relationships.map(&:name)
|
41
|
+
end
|
42
|
+
|
43
|
+
def attribute_key_values(attributes_or_relationships)
|
44
|
+
attributes_or_relationships.select { |a| a.name != a.as }
|
45
|
+
.map { |a| [a.name, a.as] }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'fun_with_json_api/exception_payload'
|
2
|
+
|
3
|
+
module FunWithJsonApi
|
4
|
+
class Exception < StandardError
|
5
|
+
attr_reader :payload
|
6
|
+
|
7
|
+
def initialize(message, payload)
|
8
|
+
super(message)
|
9
|
+
@payload = Array.wrap(payload)
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [Integer] The http status code for rendering this error
|
13
|
+
def http_status
|
14
|
+
payload_statuses = payload.map(&:status).uniq
|
15
|
+
if payload_statuses.length == 1
|
16
|
+
Integer(payload_statuses.first || '400') # Return the unique status code
|
17
|
+
elsif payload_statuses.any? { |status| status.starts_with?('5') }
|
18
|
+
500 # We have a server error
|
19
|
+
else
|
20
|
+
400 # Bad Request
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Load known Exceptions
|
27
|
+
Dir["#{File.dirname(__FILE__)}/exceptions/**/*.rb"].each { |f| require f }
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'active_model_serializers/model'
|
2
|
+
|
3
|
+
module FunWithJsonApi
|
4
|
+
# id: a unique identifier for this particular occurrence of the problem.
|
5
|
+
# links: a links object containing the following members:
|
6
|
+
# about: a link that leads to further details about this particular occurrence of the problem.
|
7
|
+
# status: the HTTP status code applicable to this problem, expressed as a string value.
|
8
|
+
# code: an application-specific error code, expressed as a string value.
|
9
|
+
# title: a short, human-readable summary of the problem that SHOULD NOT change from occurrence to
|
10
|
+
# occurrence of the problem, except for purposes of localization.
|
11
|
+
# detail: a human-readable explanation specific to this occurrence of the problem. Like title,
|
12
|
+
# this field's value can be localized.
|
13
|
+
# source: an object containing references to the source of the error, optionally including any of
|
14
|
+
# the following members:
|
15
|
+
# pointer: a JSON Pointer [RFC6901] to the associated entity in the request document
|
16
|
+
# [e.g. "/data" for a primary data object, or "/data/attributes/title" for a specific attribute].
|
17
|
+
# parameter: a string indicating which URI query parameter caused the error.
|
18
|
+
# meta: a meta object containing non-standard meta-information about the error.
|
19
|
+
class ExceptionPayload < ActiveModelSerializers::Model
|
20
|
+
[:id, :status, :code, :title, :detail, :pointer, :parameter].each do |param|
|
21
|
+
define_method param do
|
22
|
+
attributes[param]
|
23
|
+
end
|
24
|
+
define_method "#{param}=" do |value|
|
25
|
+
attributes[param] = value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module FunWithJsonApi
|
2
|
+
class ExceptionPayloadSerializer < ActiveModel::Serializer
|
3
|
+
attributes :id, :status, :code, :title, :detail, :source
|
4
|
+
|
5
|
+
def attributes(*)
|
6
|
+
# Strips all empty values and empty arrays
|
7
|
+
super.select { |_k, v| v.present? }
|
8
|
+
end
|
9
|
+
|
10
|
+
def source
|
11
|
+
{
|
12
|
+
pointer: object.pointer,
|
13
|
+
parameter: object.parameter
|
14
|
+
}.select { |_k, v| v.present? }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'fun_with_json_api/exception_payload_serializer'
|
2
|
+
|
3
|
+
module FunWithJsonApi
|
4
|
+
class ExceptionSerializer < ActiveModel::Serializer::CollectionSerializer
|
5
|
+
def initialize(exception, options = {})
|
6
|
+
super(exception.payload, options.reverse_merge(
|
7
|
+
serializer: ExceptionPayloadSerializer
|
8
|
+
))
|
9
|
+
end
|
10
|
+
|
11
|
+
def root
|
12
|
+
'errors'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module FunWithJsonApi
|
2
|
+
module Exceptions
|
3
|
+
# Indicates a Supplied attributes value is not formatted correctly
|
4
|
+
class InvalidAttribute < FunWithJsonApi::Exception
|
5
|
+
def initialize(message, payload = ExceptionPayload.new)
|
6
|
+
payload.code ||= 'invalid_attribute'
|
7
|
+
payload.title ||= I18n.t(:invalid_attribute, scope: 'fun_with_json_api.exceptions')
|
8
|
+
payload.status ||= '400'
|
9
|
+
super
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module FunWithJsonApi
|
2
|
+
module Exceptions
|
3
|
+
class InvalidDocument < FunWithJsonApi::Exception
|
4
|
+
def initialize(message, payload = ExceptionPayload.new)
|
5
|
+
payload.code ||= 'invalid_document'
|
6
|
+
payload.title ||= I18n.t(:invalid_document, scope: 'fun_with_json_api.exceptions')
|
7
|
+
payload.status ||= '400'
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module FunWithJsonApi
|
2
|
+
module Exceptions
|
3
|
+
# Indicates a Supplied relationships value is not formatted correctly
|
4
|
+
class InvalidRelationship < FunWithJsonApi::Exception
|
5
|
+
def initialize(message, payload = ExceptionPayload.new)
|
6
|
+
payload.code ||= 'invalid_relationship'
|
7
|
+
payload.title ||= I18n.t(:invalid_relationship, scope: 'fun_with_json_api.exceptions')
|
8
|
+
payload.status ||= '400'
|
9
|
+
super
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module FunWithJsonApi
|
2
|
+
module Exceptions
|
3
|
+
# Indicates a Supplied relationships value is not able to be found
|
4
|
+
class MissingRelationship < FunWithJsonApi::Exception
|
5
|
+
def initialize(message, payload = ExceptionPayload.new)
|
6
|
+
payload = Array.wrap(payload).each do |missing|
|
7
|
+
missing.code ||= 'missing_relationship'
|
8
|
+
missing.title ||= I18n.t(:missing_relationship, 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,61 @@
|
|
1
|
+
require 'active_model_serializers'
|
2
|
+
|
3
|
+
module FunWithJsonApi
|
4
|
+
# Converts a json_api document into a rails compatible hash.
|
5
|
+
# Acts as an adaptor for ActiveModuleSerializer deserializer classes
|
6
|
+
class PreDeserializer
|
7
|
+
def self.parse(document, deserializer)
|
8
|
+
new(document, deserializer).parse
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :document
|
12
|
+
attr_reader :deserializer
|
13
|
+
|
14
|
+
def initialize(document, deserializer)
|
15
|
+
@document = document.to_h.deep_dup.deep_stringify_keys
|
16
|
+
@deserializer = deserializer
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse
|
20
|
+
ams_deserializer_class.parse(document, ams_deserializer_config) do |invalid_document, reason|
|
21
|
+
exception_message = "Invalid payload (#{reason}): #{invalid_document}"
|
22
|
+
exception = convert_reason_into_exceptions(exception_message, reason).first ||
|
23
|
+
Exceptions::InvalidDocument.new(exception_message)
|
24
|
+
raise exception
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def convert_reason_into_exceptions(exception_message, reason, values = [])
|
31
|
+
if reason.is_a?(String)
|
32
|
+
return convert_reason_message_into_error(exception_message, reason, values.join)
|
33
|
+
end
|
34
|
+
return nil unless reason.is_a?(Hash)
|
35
|
+
return nil unless reason.size == 1
|
36
|
+
|
37
|
+
reason.flat_map do |key, value|
|
38
|
+
convert_reason_into_exceptions(exception_message, value, (values + ["/#{key}"]))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def convert_reason_message_into_error(exception_message, reason, source)
|
43
|
+
payload = ExceptionPayload.new
|
44
|
+
payload.pointer = source.presence
|
45
|
+
payload.detail = reason
|
46
|
+
Exceptions::InvalidDocument.new(exception_message, payload)
|
47
|
+
end
|
48
|
+
|
49
|
+
def ams_deserializer_class
|
50
|
+
if defined?(ActiveModel::Serializer::Adapter::JsonApi::Deserialization)
|
51
|
+
ActiveModel::Serializer::Adapter::JsonApi::Deserialization
|
52
|
+
else
|
53
|
+
ActiveModelSerializers::Adapter::JsonApi::Deserialization
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def ams_deserializer_config
|
58
|
+
@ams_deserializer_config ||= FunWithJsonAPi::DeserializerConfigBuilder.build(deserializer)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'fun_with_json_api/controller_methods'
|
2
|
+
|
3
|
+
module FunWithJsonApi
|
4
|
+
# Mountable engine for fun with json_api
|
5
|
+
class Railtie < Rails::Railtie
|
6
|
+
initializer 'fun_with_json_api.add_locales' do
|
7
|
+
translations = File.expand_path('../../../config/locales/**/*.{rb,yml}', __FILE__)
|
8
|
+
Dir.glob(translations) { |f| config.i18n.load_path << f.to_s }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'fun_with_json_api/exception'
|
2
|
+
require 'fun_with_json_api/attribute'
|
3
|
+
|
4
|
+
require 'fun_with_json_api/pre_deserializer'
|
5
|
+
require 'fun_with_json_api/deserializer'
|
6
|
+
require 'fun_with_json_api/deserializer_config_builder'
|
7
|
+
|
8
|
+
# Makes working with JSON:API fun!
|
9
|
+
module FunWithJsonApi
|
10
|
+
module_function
|
11
|
+
|
12
|
+
def deserialize(api_document, deserializer_class, options = {})
|
13
|
+
# Prepare the deserializer and the expected config
|
14
|
+
deserializer = deserializer_class.create(options)
|
15
|
+
|
16
|
+
# Run through initial document structure validation and deserialization
|
17
|
+
unfiltered = FunWithJsonApi::PreDeserializer.parse(api_document, deserializer)
|
18
|
+
|
19
|
+
# Ensure document matches schema, and sanitize values
|
20
|
+
deserializer.sanitize_params(unfiltered)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
require 'fun_with_json_api/railtie' if defined?(Rails)
|