fun_with_json_api 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|