jat 0.0.3 → 0.0.5
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/lib/jat/attribute.rb +36 -4
- data/lib/jat/plugins/_activerecord_preloads/_activerecord_preloads.rb +7 -3
- data/lib/jat/plugins/_activerecord_preloads/lib/preloader.rb +7 -13
- data/lib/jat/plugins/_lower_camel_case/_lower_camel_case.rb +32 -0
- data/lib/jat/plugins/_preloads/_preloads.rb +8 -2
- data/lib/jat/plugins/cache/cache.rb +9 -5
- data/lib/jat/plugins/json_api/json_api.rb +145 -105
- data/lib/jat/plugins/json_api/lib/fields_param_parser.rb +40 -0
- data/lib/jat/plugins/json_api/lib/include_param_parser.rb +84 -0
- data/lib/jat/plugins/json_api/lib/map.rb +92 -27
- data/lib/jat/plugins/json_api/lib/params/fields/validate.rb +8 -5
- data/lib/jat/plugins/json_api/lib/response.rb +84 -196
- data/lib/jat/plugins/json_api/lib/response_piece.rb +166 -0
- data/lib/jat/plugins/json_api_activerecord/json_api_activerecord.rb +31 -0
- data/lib/jat/plugins/{_json_api_activerecord → json_api_activerecord}/lib/preloads.rb +16 -24
- data/lib/jat/plugins/json_api_lower_camel_case/json_api_lower_camel_case.rb +30 -0
- data/lib/jat/plugins/json_api_maps_cache/json_api_maps_cache.rb +54 -0
- data/lib/jat/plugins/json_api_validate_params/json_api_validate_params.rb +57 -0
- data/lib/jat/plugins/json_api_validate_params/lib/params_error.rb +6 -0
- data/lib/jat/plugins/json_api_validate_params/lib/validate_fields_param.rb +59 -0
- data/lib/jat/plugins/json_api_validate_params/lib/validate_include_param.rb +33 -0
- data/lib/jat/plugins/simple_api/lib/fields_param_parser.rb +97 -0
- data/lib/jat/plugins/simple_api/lib/map.rb +80 -10
- data/lib/jat/plugins/simple_api/lib/response.rb +78 -89
- data/lib/jat/plugins/simple_api/lib/response_piece.rb +84 -0
- data/lib/jat/plugins/simple_api/simple_api.rb +83 -24
- data/lib/jat/plugins/simple_api_activerecord/lib/preloads.rb +55 -0
- data/lib/jat/plugins/simple_api_activerecord/simple_api_activerecord.rb +31 -0
- data/lib/jat/plugins/simple_api_lower_camel_case/simple_api_lower_camel_case.rb +30 -0
- data/lib/jat/plugins/simple_api_maps_cache/simple_api_maps_cache.rb +48 -0
- data/lib/jat/plugins/simple_api_validate_params/lib/fields_error.rb +6 -0
- data/lib/jat/plugins/simple_api_validate_params/lib/validate_fields_param.rb +45 -0
- data/lib/jat/plugins/simple_api_validate_params/simple_api_validate_params.rb +45 -0
- data/lib/jat/plugins/to_str/to_str.rb +10 -4
- data/lib/jat/plugins.rb +3 -16
- data/lib/jat.rb +28 -30
- data/test/lib/jat/attribute_test.rb +15 -5
- data/test/lib/jat/plugins/_activerecord_preloads/_activerecord_preloads_test.rb +34 -15
- data/test/lib/jat/plugins/_activerecord_preloads/lib/preloader_test.rb +10 -24
- data/test/lib/jat/plugins/_camel_lower/_camel_lower_test.rb +26 -0
- data/test/lib/jat/plugins/_preloads/lib/format_user_preloads_test.rb +1 -1
- data/test/lib/jat/plugins/_preloads/lib/preloads_with_path_test.rb +1 -1
- data/test/lib/jat/plugins/cache/cache_test.rb +11 -11
- data/test/lib/jat/plugins/json_api/json_api_test.rb +63 -47
- data/test/lib/jat/plugins/json_api/lib/{params/fields_test.rb → fields_param_parser_test.rb} +7 -6
- data/test/lib/jat/plugins/json_api/lib/{params/include_test.rb → include_param_parser_test.rb} +4 -4
- data/test/lib/jat/plugins/json_api/lib/map_test.rb +150 -79
- data/test/lib/jat/plugins/json_api/lib/response_test.rb +32 -32
- data/test/lib/jat/plugins/{_json_api_activerecord/_json_api_activerecord_test.rb → json_api_activerecord/json_api_activerecord_test.rb} +14 -5
- data/test/lib/jat/plugins/{_json_api_activerecord → json_api_activerecord}/lib/preloads_test.rb +11 -10
- data/test/lib/jat/plugins/json_api_camel_lower/json_api_camel_lower_test.rb +79 -0
- data/test/lib/jat/plugins/json_api_maps_cache/json_api_maps_cache_test.rb +107 -0
- data/test/lib/jat/plugins/json_api_validate_params/json_api_validate_params_test.rb +84 -0
- data/test/lib/jat/plugins/simple_api/lib/{params/parse_test.rb → fields_param_parser_test.rb} +10 -4
- data/test/lib/jat/plugins/simple_api/lib/map_test.rb +111 -34
- data/test/lib/jat/plugins/simple_api/lib/response_test.rb +80 -74
- data/test/lib/jat/plugins/simple_api/simple_api_test.rb +91 -25
- data/test/lib/jat/plugins/simple_api_activerecord/lib/preloads_test.rb +135 -0
- data/test/lib/jat/plugins/simple_api_activerecord/simple_api_activerecord_test.rb +38 -0
- data/test/lib/jat/plugins/simple_api_camel_lower/simple_api_camel_lower_test.rb +48 -0
- data/test/lib/jat/plugins/simple_api_maps_cache/simple_api_maps_cache_test.rb +95 -0
- data/test/lib/jat/plugins/simple_api_validate_params/simple_api_validate_params_test.rb +89 -0
- data/test/lib/jat/plugins/to_str/to_str_test.rb +3 -3
- data/test/lib/jat_test.rb +47 -24
- data/test/lib/plugin_test.rb +3 -3
- data/test/test_helper.rb +0 -3
- data/test/test_plugin.rb +9 -12
- metadata +60 -71
- data/CHANGELOG.md +0 -7
- data/README.md +0 -21
- data/jat.gemspec +0 -37
- data/lib/jat/plugins/_json_api_activerecord/_json_api_activerecord.rb +0 -22
- data/lib/jat/plugins/camel_lower/camel_lower.rb +0 -18
- data/lib/jat/plugins/json_api/lib/construct_traversal_map.rb +0 -91
- data/lib/jat/plugins/json_api/lib/presenters/document_links_presenter.rb +0 -48
- data/lib/jat/plugins/json_api/lib/presenters/document_meta_presenter.rb +0 -48
- data/lib/jat/plugins/json_api/lib/presenters/jsonapi_presenter.rb +0 -48
- data/lib/jat/plugins/json_api/lib/presenters/links_presenter.rb +0 -48
- data/lib/jat/plugins/json_api/lib/presenters/meta_presenter.rb +0 -48
- data/lib/jat/plugins/json_api/lib/presenters/relationship_links_presenter.rb +0 -53
- data/lib/jat/plugins/json_api/lib/presenters/relationship_meta_presenter.rb +0 -53
- data/lib/jat/plugins/json_api/lib/traversal_map.rb +0 -34
- data/lib/jat/plugins/simple_api/lib/construct_traversal_map.rb +0 -45
- data/lib/jat/plugins/simple_api/lib/params/parse.rb +0 -68
- data/lib/jat/presenter.rb +0 -51
- data/test/lib/jat/plugins/camel_lower/camel_lower_test.rb +0 -78
- data/test/lib/jat/plugins/json_api/lib/construct_traversal_map_test.rb +0 -119
- data/test/lib/jat/plugins/json_api/lib/params/fields/parse_test.rb +0 -24
- data/test/lib/jat/plugins/json_api/lib/params/fields/validate_test.rb +0 -47
- data/test/lib/jat/plugins/json_api/lib/params/include/parse_test.rb +0 -46
- data/test/lib/jat/plugins/json_api/lib/params/include/validate_test.rb +0 -51
- data/test/lib/jat/plugins/json_api/lib/presenters/document_links_presenter_test.rb +0 -69
- data/test/lib/jat/plugins/json_api/lib/presenters/document_meta_presenter_test.rb +0 -69
- data/test/lib/jat/plugins/json_api/lib/presenters/jsonapi_presenter_test.rb +0 -69
- data/test/lib/jat/plugins/json_api/lib/presenters/links_presenter_test.rb +0 -69
- data/test/lib/jat/plugins/json_api/lib/presenters/meta_presenter_test.rb +0 -69
- data/test/lib/jat/plugins/json_api/lib/presenters/relationship_links_presenter_test.rb +0 -75
- data/test/lib/jat/plugins/json_api/lib/presenters/relationship_meta_presenter_test.rb +0 -75
- data/test/lib/jat/plugins/json_api/lib/traversal_map_test.rb +0 -58
- data/test/lib/jat/plugins/simple_api/lib/construct_traversal_map_test.rb +0 -100
- data/test/lib/jat/presenter_test.rb +0 -61
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Jat
|
4
|
+
module Plugins
|
5
|
+
module JsonApi
|
6
|
+
class IncludeParamParser
|
7
|
+
module ClassMethods
|
8
|
+
COMMA = ","
|
9
|
+
DOT = "."
|
10
|
+
|
11
|
+
# Returns the Jat class that this IncludeParamParser class is namespaced under.
|
12
|
+
attr_accessor :jat_class
|
13
|
+
|
14
|
+
# Since IncludeParamParser is anonymously subclassed when Jat is subclassed,
|
15
|
+
# and then assigned to a constant of the Jat subclass, make inspect
|
16
|
+
# reflect the likely name for the class.
|
17
|
+
def inspect
|
18
|
+
"#{jat_class.inspect}::IncludeParamParser"
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse(includes_string_param)
|
22
|
+
return {} unless includes_string_param
|
23
|
+
|
24
|
+
includes_hash = parse_to_nested_hash(includes_string_param)
|
25
|
+
typed_includes(jat_class, includes_hash, {})
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def parse_to_nested_hash(includes_string_param)
|
31
|
+
includes_string_param.split(COMMA).each_with_object({}) do |part, obj|
|
32
|
+
includes = parse_part(part)
|
33
|
+
deep_merge!(obj, includes)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def typed_includes(jat_class, includes, result)
|
38
|
+
includes.each do |included_attr_name, nested_includes|
|
39
|
+
add_typed_include(result, jat_class, included_attr_name)
|
40
|
+
|
41
|
+
nested_serializer = jat_class.attributes.fetch(included_attr_name).serializer.call
|
42
|
+
typed_includes(nested_serializer, nested_includes, result)
|
43
|
+
end
|
44
|
+
|
45
|
+
result
|
46
|
+
end
|
47
|
+
|
48
|
+
def add_typed_include(result, serializer, included_attr_name)
|
49
|
+
type = serializer.get_type
|
50
|
+
|
51
|
+
includes = result[type] || []
|
52
|
+
includes |= [included_attr_name]
|
53
|
+
|
54
|
+
result[type] = includes
|
55
|
+
end
|
56
|
+
|
57
|
+
def parse_part(part)
|
58
|
+
val = {}
|
59
|
+
|
60
|
+
part.split(DOT).reverse_each do |inc|
|
61
|
+
val = {inc.to_sym => val}
|
62
|
+
end
|
63
|
+
|
64
|
+
val
|
65
|
+
end
|
66
|
+
|
67
|
+
def deep_merge!(this_hash, other_hash)
|
68
|
+
this_hash.merge!(other_hash) do |_key, this_val, other_val|
|
69
|
+
deep_merge(this_val, other_val)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def deep_merge(this_hash, other_hash)
|
74
|
+
this_hash.merge(other_hash) do |_key, this_val, other_val|
|
75
|
+
deep_merge(this_val, other_val)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
extend ClassMethods
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -1,53 +1,118 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "./params/fields"
|
4
|
-
require_relative "./params/include"
|
5
|
-
require_relative "./construct_traversal_map"
|
6
|
-
|
7
3
|
class Jat
|
8
4
|
module Plugins
|
9
5
|
module JsonApi
|
10
6
|
class Map
|
11
|
-
|
7
|
+
module ClassMethods
|
8
|
+
# Returns the Jat class that this Map class is namespaced under.
|
9
|
+
attr_accessor :jat_class
|
10
|
+
|
11
|
+
# Since Map is anonymously subclassed when Jat is subclassed,
|
12
|
+
# and then assigned to a constant of the Jat subclass, make inspect
|
13
|
+
# reflect the likely name for the class.
|
14
|
+
def inspect
|
15
|
+
"#{jat_class.inspect}::Map"
|
16
|
+
end
|
17
|
+
|
12
18
|
# Returns structure like
|
13
19
|
# {
|
14
|
-
#
|
20
|
+
# type1 => {
|
15
21
|
# attributes: [attr1, attr2, ...],
|
16
22
|
# relationships: [rel1, rel2, ...]
|
17
|
-
# }
|
23
|
+
# },
|
24
|
+
# type2 => { ... }
|
18
25
|
# }
|
19
|
-
def call(
|
20
|
-
|
21
|
-
fields =
|
22
|
-
includes =
|
26
|
+
def call(context)
|
27
|
+
exposed = context[:exposed]&.to_sym || :default
|
28
|
+
fields = context[:fields]
|
29
|
+
includes = context[:include]
|
30
|
+
|
31
|
+
construct_map(exposed, fields, includes)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def construct_map(exposed, fields, includes)
|
37
|
+
fields = jat_class::FieldsParamParser.parse(fields) if fields
|
38
|
+
includes = jat_class::IncludeParamParser.parse(includes) if includes
|
39
|
+
|
40
|
+
new(exposed, fields, includes).to_h
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
module InstanceMethods
|
45
|
+
attr_reader :jat_class, :exposed, :includes, :fields
|
23
46
|
|
24
|
-
|
25
|
-
includes_attrs = requested_includes_fields(jat, includes)
|
26
|
-
fields_attrs = requested_fields(jat, fields)
|
47
|
+
EXPOSED_TYPES = {all: :all, default: :default, none: :none}.freeze
|
27
48
|
|
28
|
-
|
49
|
+
def initialize(exposed, fields, includes)
|
50
|
+
@jat_class = self.class.jat_class
|
51
|
+
@exposed = EXPOSED_TYPES.fetch(exposed)
|
52
|
+
@fields = fields
|
53
|
+
@includes = includes
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_h
|
57
|
+
map = {}
|
58
|
+
append_map(map, jat_class)
|
59
|
+
map
|
29
60
|
end
|
30
61
|
|
31
62
|
private
|
32
63
|
|
33
|
-
def
|
34
|
-
|
64
|
+
def append_map(map, jat_class)
|
65
|
+
type = jat_class.get_type
|
66
|
+
return map if map.key?(type)
|
67
|
+
|
68
|
+
type_map = {serializer: jat_class}
|
69
|
+
map[type] = type_map
|
70
|
+
|
71
|
+
fill_type_map(map, type_map, type, jat_class)
|
72
|
+
|
73
|
+
type_map[:attributes] ||= FROZEN_EMPTY_ARRAY
|
74
|
+
type_map[:relationships] ||= FROZEN_EMPTY_ARRAY
|
75
|
+
end
|
76
|
+
|
77
|
+
def fill_type_map(map, type_map, type, jat_class)
|
78
|
+
jat_class.attributes.each_value do |attribute|
|
79
|
+
next unless expose?(type, attribute)
|
35
80
|
|
36
|
-
|
37
|
-
|
38
|
-
.new(jat.class, :exposed, manually_exposed: include_types)
|
39
|
-
.to_h
|
81
|
+
fill_attr(map, type_map, attribute)
|
82
|
+
end
|
40
83
|
end
|
41
84
|
|
42
|
-
def
|
43
|
-
|
85
|
+
def fill_attr(map, type_map, attribute)
|
86
|
+
name = attribute.name
|
44
87
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
88
|
+
if attribute.relation?
|
89
|
+
(type_map[:relationships] ||= []) << name
|
90
|
+
append_map(map, attribute.serializer.call)
|
91
|
+
else
|
92
|
+
(type_map[:attributes] ||= []) << name
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def expose?(type, attribute)
|
97
|
+
attribute_name = attribute.name
|
98
|
+
fields_attribute_names = fields && fields[type]
|
99
|
+
return fields_attribute_names.include?(attribute_name) if fields_attribute_names
|
100
|
+
|
101
|
+
includes_attribute_names = includes && includes[type]
|
102
|
+
includes_attribute_names&.include?(attribute_name) || attribute_exposed?(attribute)
|
103
|
+
end
|
104
|
+
|
105
|
+
def attribute_exposed?(attribute)
|
106
|
+
case exposed
|
107
|
+
when :all then true
|
108
|
+
when :none then false
|
109
|
+
else attribute.exposed?
|
110
|
+
end
|
49
111
|
end
|
50
112
|
end
|
113
|
+
|
114
|
+
extend ClassMethods
|
115
|
+
include InstanceMethods
|
51
116
|
end
|
52
117
|
end
|
53
118
|
end
|
@@ -8,17 +8,20 @@ class Jat
|
|
8
8
|
class Validate
|
9
9
|
class << self
|
10
10
|
def call(jat, fields)
|
11
|
+
full_map = jat.maps.full
|
12
|
+
|
11
13
|
fields.each do |type, attributes_names|
|
12
|
-
new(jat, type).validate(attributes_names)
|
14
|
+
new(jat, type, full_map).validate(attributes_names)
|
13
15
|
end
|
14
16
|
end
|
15
17
|
end
|
16
18
|
|
17
|
-
attr_reader :jat, :type
|
19
|
+
attr_reader :jat, :type, :full_map
|
18
20
|
|
19
|
-
def initialize(jat, type)
|
21
|
+
def initialize(jat, type, full_map)
|
20
22
|
@jat = jat
|
21
23
|
@type = type
|
24
|
+
@full_map = full_map
|
22
25
|
end
|
23
26
|
|
24
27
|
def validate(attributes_names)
|
@@ -29,7 +32,7 @@ class Jat
|
|
29
32
|
private
|
30
33
|
|
31
34
|
def check_fields_type
|
32
|
-
return if
|
35
|
+
return if full_map.key?(type)
|
33
36
|
|
34
37
|
raise Error, "#{jat.class} and its children have no requested type `#{type}`"
|
35
38
|
end
|
@@ -41,7 +44,7 @@ class Jat
|
|
41
44
|
end
|
42
45
|
|
43
46
|
def check_attribute_name(attribute_name)
|
44
|
-
type_data =
|
47
|
+
type_data = full_map.fetch(type)
|
45
48
|
type_serializer = type_data.fetch(:serializer)
|
46
49
|
return if type_serializer.attributes.key?(attribute_name)
|
47
50
|
|
@@ -5,234 +5,122 @@ class Jat
|
|
5
5
|
module Plugins
|
6
6
|
module JsonApi
|
7
7
|
class Response
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
def response
|
18
|
-
data, includes = data_with_includes
|
19
|
-
meta = document_meta
|
20
|
-
links = document_links
|
21
|
-
jsonapi = jsonapi_data
|
22
|
-
|
23
|
-
result = {}
|
24
|
-
result[:links] = links if links.any?
|
25
|
-
result[:data] = data if data
|
26
|
-
result[:included] = includes.values if includes.any?
|
27
|
-
result[:meta] = meta if meta.any?
|
28
|
-
result[:jsonapi] = jsonapi if jsonapi.any?
|
29
|
-
result
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def data_with_includes
|
35
|
-
includes = {}
|
36
|
-
data = many?(object, context) ? many(object, includes) : one(object, includes)
|
37
|
-
[data, includes]
|
38
|
-
end
|
39
|
-
|
40
|
-
def many(objs, includes)
|
41
|
-
objs.map { |obj| one(obj, includes) }
|
42
|
-
end
|
43
|
-
|
44
|
-
def one(obj, includes)
|
45
|
-
ResponseData.new(jat_class, obj, context, full_map, includes).data
|
46
|
-
end
|
47
|
-
|
48
|
-
def many?(data, context)
|
49
|
-
many = context[:many]
|
50
|
-
many.nil? ? data.is_a?(Enumerable) : many
|
51
|
-
end
|
52
|
-
|
53
|
-
def full_map
|
54
|
-
@full_map ||= jat.traversal_map.current
|
55
|
-
end
|
56
|
-
|
57
|
-
def jsonapi_data
|
58
|
-
data = context[:jsonapi]&.transform_keys(&:to_sym) || {}
|
59
|
-
jsonapi_data = jat_class.jsonapi_data
|
60
|
-
return data if jsonapi_data.empty?
|
61
|
-
|
62
|
-
presenter = jat_class::JsonapiPresenter.new(object, context)
|
63
|
-
jsonapi_data.each_key do |key|
|
64
|
-
data[key] = presenter.public_send(key) unless data.key?(key)
|
8
|
+
module ClassMethods
|
9
|
+
# Returns the Jat class that this Response class is namespaced under.
|
10
|
+
attr_accessor :jat_class
|
11
|
+
|
12
|
+
# Since Response is anonymously subclassed when Jat is subclassed,
|
13
|
+
# and then assigned to a constant of the Jat subclass, make inspect
|
14
|
+
# reflect the likely name for the class.
|
15
|
+
def inspect
|
16
|
+
"#{jat_class.inspect}::Response"
|
65
17
|
end
|
66
|
-
data.compact!
|
67
|
-
data
|
68
|
-
end
|
69
18
|
|
70
|
-
|
71
|
-
|
72
|
-
document_links = jat_class.document_links
|
73
|
-
return data if document_links.empty?
|
74
|
-
|
75
|
-
presenter = jat_class::DocumentLinksPresenter.new(object, context)
|
76
|
-
document_links.each_key do |key|
|
77
|
-
data[key] = presenter.public_send(key) unless data.key?(key)
|
19
|
+
def call(object, context)
|
20
|
+
new(object, context).to_h
|
78
21
|
end
|
79
|
-
data.compact!
|
80
|
-
data
|
81
22
|
end
|
82
23
|
|
83
|
-
|
84
|
-
|
85
|
-
document_meta = jat_class.added_document_meta
|
86
|
-
return data if document_meta.empty?
|
24
|
+
module InstanceMethods
|
25
|
+
attr_reader :jat_class, :object, :context
|
87
26
|
|
88
|
-
|
89
|
-
|
90
|
-
|
27
|
+
def initialize(object, context)
|
28
|
+
@object = object
|
29
|
+
@context = context
|
30
|
+
@jat_class = self.class.jat_class
|
91
31
|
end
|
92
|
-
data.compact!
|
93
|
-
data
|
94
|
-
end
|
95
|
-
end
|
96
32
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
@object = object
|
103
|
-
@context = context
|
104
|
-
@includes = includes
|
105
|
-
@full_map = full_map
|
106
|
-
@map = full_map.fetch(jat_class.type)
|
107
|
-
@presenter = jat_class::Presenter.new(object, context)
|
108
|
-
end
|
109
|
-
|
110
|
-
def data
|
111
|
-
return unless object
|
112
|
-
|
113
|
-
attributes = get_attributes
|
114
|
-
relationships = get_relationships
|
115
|
-
links = get_links
|
116
|
-
meta = get_meta
|
33
|
+
def to_h
|
34
|
+
data, includes = data_with_includes
|
35
|
+
meta = document_meta
|
36
|
+
links = document_links
|
37
|
+
jsonapi = jsonapi_data
|
117
38
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
def uid
|
127
|
-
{type: jat_class.type, id: presenter.id}
|
128
|
-
end
|
39
|
+
result = {}
|
40
|
+
result[:links] = links if links.any?
|
41
|
+
result[:data] = data if data
|
42
|
+
result[:included] = includes.values if includes.any?
|
43
|
+
result[:meta] = meta if meta.any?
|
44
|
+
result[:jsonapi] = jsonapi if jsonapi.any?
|
45
|
+
result
|
46
|
+
end
|
129
47
|
|
130
|
-
|
48
|
+
private
|
131
49
|
|
132
|
-
|
133
|
-
|
134
|
-
|
50
|
+
def data_with_includes
|
51
|
+
includes = {}
|
52
|
+
map = jat_class::Map.call(context)
|
53
|
+
data = many?(object, context) ? many(object, includes, map) : one(object, includes, map)
|
54
|
+
[data, includes]
|
55
|
+
end
|
135
56
|
|
136
|
-
|
137
|
-
|
138
|
-
attrs[name] = presenter.public_send(attribute.original_name)
|
57
|
+
def many(objects, includes, map)
|
58
|
+
objects.map { |object| one(object, includes, map) }
|
139
59
|
end
|
140
|
-
end
|
141
60
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
relationships_names.each_with_object({}) do |name, rels|
|
147
|
-
rel_attribute = jat_class.attributes[name]
|
148
|
-
rel_object = presenter.public_send(rel_attribute.original_name)
|
149
|
-
|
150
|
-
rel_serializer = rel_attribute.serializer.call
|
151
|
-
rel_links = get_relationship_links(rel_serializer, rel_object)
|
152
|
-
rel_meta = get_relationship_meta(rel_serializer, rel_object)
|
153
|
-
rel_data =
|
154
|
-
if many?(rel_attribute, rel_object)
|
155
|
-
many_relationships_data(rel_serializer, rel_object)
|
156
|
-
else
|
157
|
-
one_relationship_data(rel_serializer, rel_object)
|
158
|
-
end
|
61
|
+
def one(object, includes, map)
|
62
|
+
jat_class::ResponsePiece.call(object, context, map, includes)
|
63
|
+
end
|
159
64
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
result[:meta] = rel_meta if rel_meta.any?
|
164
|
-
rels[name] = result
|
65
|
+
def many?(data, context)
|
66
|
+
many = context[:many]
|
67
|
+
many.nil? ? data.is_a?(Enumerable) : many
|
165
68
|
end
|
166
|
-
end
|
167
69
|
|
168
|
-
|
169
|
-
|
70
|
+
def jsonapi_data
|
71
|
+
combine(jat_class.jsonapi_data, context_jsonapi)
|
72
|
+
end
|
170
73
|
|
171
|
-
|
172
|
-
|
74
|
+
def document_links
|
75
|
+
combine(jat_class.document_links, context_links)
|
76
|
+
end
|
173
77
|
|
174
|
-
|
175
|
-
|
78
|
+
def document_meta
|
79
|
+
combine(jat_class.added_document_meta, context_meta)
|
80
|
+
end
|
176
81
|
|
177
|
-
|
178
|
-
|
82
|
+
def combine(attributes, context_data)
|
83
|
+
return context_data if attributes.empty?
|
179
84
|
|
180
|
-
|
181
|
-
rel_response_data = self.class.new(rel_serializer, rel_object, context, full_map, includes)
|
182
|
-
rel_uid = rel_response_data.uid
|
183
|
-
includes[rel_uid] ||= rel_response_data.data
|
184
|
-
rel_uid
|
185
|
-
end
|
85
|
+
data = context_data
|
186
86
|
|
187
|
-
|
188
|
-
|
87
|
+
attributes.each do |name, attribute|
|
88
|
+
next if data.key?(name)
|
189
89
|
|
190
|
-
|
191
|
-
return is_many if (is_many == true) || (is_many == false)
|
90
|
+
value = attribute_value(attribute)
|
192
91
|
|
193
|
-
|
194
|
-
|
195
|
-
|
92
|
+
unless value.nil?
|
93
|
+
data = data.dup if data.equal?(FROZEN_EMPTY_HASH)
|
94
|
+
data[name] = value
|
95
|
+
end
|
96
|
+
end
|
196
97
|
|
197
|
-
|
198
|
-
|
199
|
-
return links if links.empty?
|
98
|
+
data
|
99
|
+
end
|
200
100
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
result
|
205
|
-
end
|
101
|
+
def attribute_value(attribute)
|
102
|
+
attribute.block.call(object, context)
|
103
|
+
end
|
206
104
|
|
207
|
-
|
208
|
-
|
209
|
-
|
105
|
+
def context_jsonapi
|
106
|
+
context_attr_transform(:jsonapi)
|
107
|
+
end
|
210
108
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
result
|
215
|
-
end
|
109
|
+
def context_links
|
110
|
+
context_attr_transform(:links)
|
111
|
+
end
|
216
112
|
|
217
|
-
|
218
|
-
|
219
|
-
|
113
|
+
def context_meta
|
114
|
+
context_attr_transform(:meta)
|
115
|
+
end
|
220
116
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
result
|
117
|
+
def context_attr_transform(key)
|
118
|
+
context[key]&.transform_keys(&:to_sym) || FROZEN_EMPTY_HASH
|
119
|
+
end
|
225
120
|
end
|
226
121
|
|
227
|
-
|
228
|
-
|
229
|
-
return meta if meta.empty?
|
230
|
-
|
231
|
-
presenter = rel_serializer::RelationshipMetaPresenter.new(object, rel_object, context)
|
232
|
-
result = meta.each_key.each_with_object({}) { |key, data| data[key] = presenter.public_send(key) }
|
233
|
-
result.compact!
|
234
|
-
result
|
235
|
-
end
|
122
|
+
extend ClassMethods
|
123
|
+
include InstanceMethods
|
236
124
|
end
|
237
125
|
end
|
238
126
|
end
|