serega 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/serega/attribute.rb +6 -1
- data/lib/serega/config.rb +2 -2
- data/lib/serega/map.rb +2 -4
- data/lib/serega/map_point.rb +34 -0
- data/lib/serega/object_serializer.rb +67 -0
- data/lib/serega/plugins/activerecord_preloads/activerecord_preloads.rb +4 -0
- data/lib/serega/plugins/activerecord_preloads/lib/preloader.rb +27 -8
- data/lib/serega/plugins/batch/batch.rb +189 -0
- data/lib/serega/plugins/batch/lib/loader.rb +60 -0
- data/lib/serega/plugins/batch/lib/loaders.rb +32 -0
- data/lib/serega/plugins/batch/lib/plugins_extensions.rb +40 -0
- data/lib/serega/plugins/batch/lib/validations/check_batch_opt_key.rb +61 -0
- data/lib/serega/plugins/batch/lib/validations/check_batch_opt_loader.rb +61 -0
- data/lib/serega/plugins/batch/lib/validations/check_opt_batch.rb +47 -0
- data/lib/serega/plugins/context_metadata/context_metadata.rb +4 -4
- data/lib/serega/plugins/formatters/formatters.rb +25 -13
- data/lib/serega/plugins/hide_nil/hide_nil.rb +4 -4
- data/lib/serega/plugins/metadata/metadata.rb +11 -11
- data/lib/serega/plugins/preloads/lib/preloads_constructor.rb +8 -6
- data/lib/serega/plugins/preloads/preloads.rb +12 -1
- data/lib/serega/plugins/presenter/presenter.rb +6 -5
- data/lib/serega/plugins/root/root.rb +12 -12
- data/lib/serega/plugins/string_modifiers/parse_string_modifiers.rb +1 -1
- data/lib/serega/serializer.rb +32 -0
- data/lib/serega.rb +15 -10
- metadata +12 -5
- data/lib/serega/convert.rb +0 -45
- data/lib/serega/convert_item.rb +0 -37
- data/lib/serega/plugins/lazy/lazy.rb +0 -53
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module SeregaPlugins
|
5
|
+
module Batch
|
6
|
+
class CheckOptBatch
|
7
|
+
class << self
|
8
|
+
def call(opts, block)
|
9
|
+
return unless opts.key?(:batch)
|
10
|
+
|
11
|
+
SeregaValidations::Utils::CheckOptIsHash.call(opts, :batch)
|
12
|
+
|
13
|
+
batch = opts[:batch]
|
14
|
+
SeregaValidations::Utils::CheckAllowedKeys.call(batch, %i[key loader default])
|
15
|
+
|
16
|
+
check_batch_opt_key(batch[:key])
|
17
|
+
check_batch_opt_loader(batch[:loader])
|
18
|
+
|
19
|
+
check_usage_with_other_params(opts, block)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def check_batch_opt_key(key)
|
25
|
+
raise SeregaError, "Option :key must present inside :batch option" unless key
|
26
|
+
|
27
|
+
CheckBatchOptKey.call(key)
|
28
|
+
end
|
29
|
+
|
30
|
+
def check_batch_opt_loader(loader)
|
31
|
+
raise SeregaError, "Option :loader must present inside :batch option" unless loader
|
32
|
+
|
33
|
+
CheckBatchOptLoader.call(loader)
|
34
|
+
end
|
35
|
+
|
36
|
+
def check_usage_with_other_params(opts, block)
|
37
|
+
raise SeregaError, "Option :batch can not be used together with option :key" if opts.key?(:key)
|
38
|
+
raise SeregaError, "Option :batch can not be used together with option :value" if opts.key?(:value)
|
39
|
+
raise SeregaError, "Option :batch can not be used together with option :const" if opts.key?(:const)
|
40
|
+
raise SeregaError, "Option :batch can not be used together with option :delegate" if opts.key?(:delegate)
|
41
|
+
raise SeregaError, "Option :batch can not be used together with block" if block
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -15,7 +15,7 @@ class Serega
|
|
15
15
|
|
16
16
|
def self.load_plugin(serializer_class, **_opts)
|
17
17
|
serializer_class::SeregaConfig.include(ConfigInstanceMethods)
|
18
|
-
serializer_class::
|
18
|
+
serializer_class::SeregaSerializer.include(SeregaSerializerInstanceMethods)
|
19
19
|
serializer_class::CheckSerializeParams.include(CheckSerializeParamsInstanceMethods)
|
20
20
|
end
|
21
21
|
|
@@ -44,7 +44,7 @@ class Serega
|
|
44
44
|
|
45
45
|
module ConfigInstanceMethods
|
46
46
|
def context_metadata
|
47
|
-
ContextMetadataConfig.new(opts.fetch(:context_metadata))
|
47
|
+
@context_metadata ||= ContextMetadataConfig.new(opts.fetch(:context_metadata))
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -57,8 +57,8 @@ class Serega
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
module
|
61
|
-
def
|
60
|
+
module SeregaSerializerInstanceMethods
|
61
|
+
def serialize(object)
|
62
62
|
super.tap do |hash|
|
63
63
|
add_context_metadata(hash)
|
64
64
|
end
|
@@ -7,6 +7,12 @@ class Serega
|
|
7
7
|
:formatters
|
8
8
|
end
|
9
9
|
|
10
|
+
def self.before_load_plugin(serializer_class, **opts)
|
11
|
+
if serializer_class.plugin_used?(:batch)
|
12
|
+
raise SeregaError, "Plugin `formatters` must be loaded before `batch`"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
10
16
|
def self.load_plugin(serializer_class, **_opts)
|
11
17
|
serializer_class::SeregaConfig.include(ConfigInstanceMethods)
|
12
18
|
serializer_class::SeregaAttribute.include(AttributeInstanceMethods)
|
@@ -35,21 +41,32 @@ class Serega
|
|
35
41
|
|
36
42
|
module ConfigInstanceMethods
|
37
43
|
def formatters
|
38
|
-
FormattersConfig.new(opts.fetch(:formatters))
|
44
|
+
@formatters ||= FormattersConfig.new(opts.fetch(:formatters))
|
39
45
|
end
|
40
46
|
end
|
41
47
|
|
42
48
|
module AttributeInstanceMethods
|
43
|
-
def
|
44
|
-
return @
|
49
|
+
def formatter
|
50
|
+
return @formatter if instance_variable_defined?(:@formatter)
|
51
|
+
|
52
|
+
@formatter = formatter_resolved
|
53
|
+
end
|
45
54
|
|
46
|
-
|
55
|
+
def formatter_resolved
|
47
56
|
formatter = opts[:format]
|
48
|
-
return
|
57
|
+
return unless formatter
|
49
58
|
|
50
|
-
|
59
|
+
formatter = self.class.serializer_class.config.formatters.opts.fetch(formatter) if formatter.is_a?(Symbol)
|
60
|
+
formatter
|
61
|
+
end
|
62
|
+
|
63
|
+
def value_block
|
64
|
+
return @value_block if instance_variable_defined?(:@value_block)
|
65
|
+
return @value_block = super unless formatter
|
66
|
+
|
67
|
+
new_value_block = formatted_block(formatter, super)
|
51
68
|
|
52
|
-
#
|
69
|
+
# Format :const value in advance
|
53
70
|
if opts.key?(:const)
|
54
71
|
const_value = new_value_block.call
|
55
72
|
new_value_block = proc { const_value }
|
@@ -63,12 +80,7 @@ class Serega
|
|
63
80
|
def formatted_block(formatter, original_block)
|
64
81
|
proc do |object, context|
|
65
82
|
value = original_block.call(object, context)
|
66
|
-
|
67
|
-
if formatter.is_a?(Symbol)
|
68
|
-
self.class.serializer_class.config.formatters.opts.fetch(formatter).call(value)
|
69
|
-
else
|
70
|
-
formatter.call(value)
|
71
|
-
end
|
83
|
+
formatter.call(value)
|
72
84
|
end
|
73
85
|
end
|
74
86
|
end
|
@@ -23,7 +23,7 @@ class Serega
|
|
23
23
|
def self.load_plugin(serializer_class, **_opts)
|
24
24
|
serializer_class::SeregaAttribute.include(AttributeMethods)
|
25
25
|
serializer_class::CheckAttributeParams.include(CheckAttributeParamsInstanceMethods)
|
26
|
-
serializer_class::
|
26
|
+
serializer_class::SeregaObjectSerializer.include(SeregaObjectSerializerInstanceMethods)
|
27
27
|
end
|
28
28
|
|
29
29
|
def self.after_load_plugin(serializer_class, **opts)
|
@@ -66,11 +66,11 @@ class Serega
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
-
module
|
69
|
+
module SeregaObjectSerializerInstanceMethods
|
70
70
|
private
|
71
71
|
|
72
|
-
def
|
73
|
-
super unless
|
72
|
+
def attach_final_value(final_value, *)
|
73
|
+
super unless final_value.nil?
|
74
74
|
end
|
75
75
|
end
|
76
76
|
end
|
@@ -20,7 +20,7 @@ class Serega
|
|
20
20
|
def self.load_plugin(serializer_class, **_opts)
|
21
21
|
serializer_class.extend(ClassMethods)
|
22
22
|
serializer_class::SeregaConfig.include(ConfigInstanceMethods)
|
23
|
-
serializer_class::
|
23
|
+
serializer_class::SeregaSerializer.include(SeregaSerializerInstanceMethods)
|
24
24
|
|
25
25
|
require_relative "./meta_attribute"
|
26
26
|
require_relative "./validations/check_block"
|
@@ -52,7 +52,7 @@ class Serega
|
|
52
52
|
|
53
53
|
module ConfigInstanceMethods
|
54
54
|
def metadata
|
55
|
-
MetadataConfig.new(opts.fetch(:metadata))
|
55
|
+
@metadata ||= MetadataConfig.new(opts.fetch(:metadata))
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
@@ -104,26 +104,26 @@ class Serega
|
|
104
104
|
end
|
105
105
|
end
|
106
106
|
|
107
|
-
module
|
108
|
-
def
|
109
|
-
|
110
|
-
|
111
|
-
|
107
|
+
module SeregaSerializerInstanceMethods
|
108
|
+
def serialize(object)
|
109
|
+
super.tap do |hash|
|
110
|
+
add_metadata(object, hash)
|
111
|
+
end
|
112
112
|
end
|
113
113
|
|
114
114
|
private
|
115
115
|
|
116
|
-
def add_metadata(hash)
|
116
|
+
def add_metadata(object, hash)
|
117
117
|
self.class.serializer_class.meta_attributes.each_value do |meta_attribute|
|
118
|
-
metadata = meta_attribute_value(meta_attribute)
|
118
|
+
metadata = meta_attribute_value(object, meta_attribute)
|
119
119
|
next unless metadata
|
120
120
|
|
121
121
|
deep_merge_metadata(hash, metadata)
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
125
|
-
def meta_attribute_value(meta_attribute)
|
126
|
-
value = meta_attribute.value(object,
|
125
|
+
def meta_attribute_value(object, meta_attribute)
|
126
|
+
value = meta_attribute.value(object, context)
|
127
127
|
return if meta_attribute.hide?(value)
|
128
128
|
|
129
129
|
# Example:
|
@@ -16,6 +16,8 @@ class Serega
|
|
16
16
|
# @return [Hash]
|
17
17
|
#
|
18
18
|
def call(map)
|
19
|
+
return FROZEN_EMPTY_HASH unless map
|
20
|
+
|
19
21
|
preloads = {}
|
20
22
|
append_many(preloads, map)
|
21
23
|
preloads
|
@@ -24,17 +26,17 @@ class Serega
|
|
24
26
|
private
|
25
27
|
|
26
28
|
def append_many(preloads, map)
|
27
|
-
map.each do |
|
28
|
-
current_preloads = attribute.preloads
|
29
|
+
map.each do |point|
|
30
|
+
current_preloads = point.attribute.preloads
|
29
31
|
next unless current_preloads
|
30
32
|
|
31
|
-
has_nested =
|
33
|
+
has_nested = point.has_nested_points?
|
32
34
|
current_preloads = SeregaUtils::EnumDeepDup.call(current_preloads) if has_nested
|
33
35
|
append_current(preloads, current_preloads)
|
34
36
|
next unless has_nested
|
35
37
|
|
36
|
-
nested_preloads = nested(preloads,
|
37
|
-
append_many(nested_preloads,
|
38
|
+
nested_preloads = nested(preloads, point.preloads_path)
|
39
|
+
append_many(nested_preloads, point.nested_points)
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
@@ -49,7 +51,7 @@ class Serega
|
|
49
51
|
end
|
50
52
|
|
51
53
|
def nested(preloads, path)
|
52
|
-
!path || path.empty? ? preloads : preloads.dig(*path)
|
54
|
+
(!path || path.empty?) ? preloads : preloads.dig(*path)
|
53
55
|
end
|
54
56
|
end
|
55
57
|
|
@@ -29,6 +29,7 @@ class Serega
|
|
29
29
|
serializer_class.include(InstanceMethods)
|
30
30
|
serializer_class::SeregaAttribute.include(AttributeMethods)
|
31
31
|
serializer_class::SeregaConfig.include(ConfigInstanceMethods)
|
32
|
+
serializer_class::SeregaMapPoint.include(MapPointMethods)
|
32
33
|
|
33
34
|
serializer_class::CheckAttributeParams.include(CheckAttributeParamsInstanceMethods)
|
34
35
|
|
@@ -85,7 +86,7 @@ class Serega
|
|
85
86
|
|
86
87
|
module ConfigInstanceMethods
|
87
88
|
def preloads
|
88
|
-
PreloadsConfig.new(opts.fetch(:preloads))
|
89
|
+
@preloads ||= PreloadsConfig.new(opts.fetch(:preloads))
|
89
90
|
end
|
90
91
|
end
|
91
92
|
|
@@ -142,6 +143,16 @@ class Serega
|
|
142
143
|
end
|
143
144
|
end
|
144
145
|
|
146
|
+
module MapPointMethods
|
147
|
+
def preloads
|
148
|
+
@preloads ||= PreloadsConstructor.call(nested_points)
|
149
|
+
end
|
150
|
+
|
151
|
+
def preloads_path
|
152
|
+
attribute.preloads_path
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
145
156
|
module CheckAttributeParamsInstanceMethods
|
146
157
|
private
|
147
158
|
|
@@ -35,7 +35,7 @@ class Serega
|
|
35
35
|
#
|
36
36
|
def self.load_plugin(serializer_class, **_opts)
|
37
37
|
serializer_class.extend(ClassMethods)
|
38
|
-
serializer_class::
|
38
|
+
serializer_class::SeregaSerializer.include(SeregaSerializerInstanceMethods)
|
39
39
|
end
|
40
40
|
|
41
41
|
#
|
@@ -94,13 +94,14 @@ class Serega
|
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
|
-
# Includes methods to override
|
98
|
-
module
|
97
|
+
# Includes methods to override SeregaSerializer class
|
98
|
+
module SeregaSerializerInstanceMethods
|
99
99
|
#
|
100
100
|
# Replaces serialized object with Presenter.new(object)
|
101
101
|
#
|
102
|
-
def
|
103
|
-
|
102
|
+
def serialize(object)
|
103
|
+
presenter_class = points.first.class.serializer_class::Presenter
|
104
|
+
object = presenter_class.new(object)
|
104
105
|
super
|
105
106
|
end
|
106
107
|
end
|
@@ -12,8 +12,8 @@ class Serega
|
|
12
12
|
|
13
13
|
def self.load_plugin(serializer_class, **_opts)
|
14
14
|
serializer_class.extend(ClassMethods)
|
15
|
-
serializer_class::SeregaConfig.include(
|
16
|
-
serializer_class::
|
15
|
+
serializer_class::SeregaConfig.include(ConfigInstanceMethods)
|
16
|
+
serializer_class::SeregaSerializer.include(SerializerInstanceMethods)
|
17
17
|
end
|
18
18
|
|
19
19
|
def self.after_load_plugin(serializer_class, **opts)
|
@@ -70,9 +70,9 @@ class Serega
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
-
module
|
73
|
+
module ConfigInstanceMethods
|
74
74
|
def root
|
75
|
-
RootConfig.new(opts.fetch(:root))
|
75
|
+
@root ||= RootConfig.new(opts.fetch(:root))
|
76
76
|
end
|
77
77
|
|
78
78
|
def root=(value)
|
@@ -81,21 +81,21 @@ class Serega
|
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
|
-
module
|
85
|
-
def
|
86
|
-
|
87
|
-
root = build_root(opts)
|
88
|
-
|
89
|
-
|
84
|
+
module SerializerInstanceMethods
|
85
|
+
def serialize(_object)
|
86
|
+
result = super
|
87
|
+
root = build_root(result, opts)
|
88
|
+
result = {root => result} if root
|
89
|
+
result
|
90
90
|
end
|
91
91
|
|
92
92
|
private
|
93
93
|
|
94
|
-
def build_root(opts)
|
94
|
+
def build_root(result, opts)
|
95
95
|
return opts[:root] if opts.key?(:root)
|
96
96
|
|
97
97
|
root = self.class.serializer_class.config.root
|
98
|
-
|
98
|
+
result.is_a?(Array) ? root.many : root.one
|
99
99
|
end
|
100
100
|
end
|
101
101
|
end
|
@@ -53,7 +53,7 @@ class Serega
|
|
53
53
|
name = attribute.to_sym
|
54
54
|
attribute.clear
|
55
55
|
|
56
|
-
current_attrs = !path_stack || path_stack.empty? ? res : res.dig(*path_stack)
|
56
|
+
current_attrs = (!path_stack || path_stack.empty?) ? res : res.dig(*path_stack)
|
57
57
|
current_attrs[name] = nested_attributes
|
58
58
|
|
59
59
|
name
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
class SeregaSerializer
|
5
|
+
module SeregaSerializerInstanceMethods
|
6
|
+
# @param context [Hash] Serialization context
|
7
|
+
# @param many [TrueClass|FalseClass] is object is enumerable
|
8
|
+
# @param points [Array<MapPoint>] Serialization points (attributes)
|
9
|
+
# @param opts [Hash] Any custom options
|
10
|
+
def initialize(context:, points:, many: nil, **opts)
|
11
|
+
@context = context
|
12
|
+
@points = points
|
13
|
+
@many = many
|
14
|
+
@opts = opts
|
15
|
+
end
|
16
|
+
|
17
|
+
# @param object [Object] Serialized object
|
18
|
+
def serialize(object)
|
19
|
+
self.class.serializer_class::SeregaObjectSerializer
|
20
|
+
.new(context: context, points: points, many: many, **opts)
|
21
|
+
.serialize(object)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
attr_reader :context, :points, :many, :opts
|
27
|
+
end
|
28
|
+
|
29
|
+
extend Serega::SeregaHelpers::SerializerClassHelper
|
30
|
+
include SeregaSerializerInstanceMethods
|
31
|
+
end
|
32
|
+
end
|
data/lib/serega.rb
CHANGED
@@ -37,8 +37,9 @@ require_relative "serega/validations/check_initiate_params"
|
|
37
37
|
require_relative "serega/validations/check_serialize_params"
|
38
38
|
|
39
39
|
require_relative "serega/config"
|
40
|
-
require_relative "serega/
|
41
|
-
require_relative "serega/
|
40
|
+
require_relative "serega/object_serializer"
|
41
|
+
require_relative "serega/serializer"
|
42
|
+
require_relative "serega/map_point"
|
42
43
|
require_relative "serega/map"
|
43
44
|
require_relative "serega/plugins"
|
44
45
|
|
@@ -79,13 +80,17 @@ class Serega
|
|
79
80
|
map_class.serializer_class = subclass
|
80
81
|
subclass.const_set(:SeregaMap, map_class)
|
81
82
|
|
82
|
-
|
83
|
-
|
84
|
-
subclass.const_set(:
|
83
|
+
map_point_class = Class.new(self::SeregaMapPoint)
|
84
|
+
map_point_class.serializer_class = subclass
|
85
|
+
subclass.const_set(:SeregaMapPoint, map_point_class)
|
85
86
|
|
86
|
-
|
87
|
-
|
88
|
-
subclass.const_set(:
|
87
|
+
serega_serializer_class = Class.new(self::SeregaSerializer)
|
88
|
+
serega_serializer_class.serializer_class = subclass
|
89
|
+
subclass.const_set(:SeregaSerializer, serega_serializer_class)
|
90
|
+
|
91
|
+
object_serializer_class = Class.new(self::SeregaObjectSerializer)
|
92
|
+
object_serializer_class.serializer_class = subclass
|
93
|
+
subclass.const_set(:SeregaObjectSerializer, object_serializer_class)
|
89
94
|
|
90
95
|
check_attribute_params_class = Class.new(self::CheckAttributeParams)
|
91
96
|
check_attribute_params_class.serializer_class = subclass
|
@@ -208,7 +213,7 @@ class Serega
|
|
208
213
|
# @param with [Array, Hash, String, Symbol] Attributes (usually hidden) to serialize additionally
|
209
214
|
#
|
210
215
|
def initialize(opts = FROZEN_EMPTY_HASH)
|
211
|
-
@opts = opts == FROZEN_EMPTY_HASH ? opts : prepare_modifiers(opts)
|
216
|
+
@opts = (opts == FROZEN_EMPTY_HASH) ? opts : prepare_modifiers(opts)
|
212
217
|
self.class::CheckInitiateParams.new(@opts).validate if opts.fetch(:check_initiate_params) { config.check_initiate_params }
|
213
218
|
end
|
214
219
|
|
@@ -224,7 +229,7 @@ class Serega
|
|
224
229
|
self.class::CheckSerializeParams.new(opts).validate
|
225
230
|
opts[:context] ||= {}
|
226
231
|
|
227
|
-
self.class::
|
232
|
+
self.class::SeregaSerializer.new(points: map, **opts).serialize(object)
|
228
233
|
end
|
229
234
|
|
230
235
|
# @see #call
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: serega
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrey Glushkov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-11-21 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -21,21 +21,27 @@ files:
|
|
21
21
|
- lib/serega.rb
|
22
22
|
- lib/serega/attribute.rb
|
23
23
|
- lib/serega/config.rb
|
24
|
-
- lib/serega/convert.rb
|
25
|
-
- lib/serega/convert_item.rb
|
26
24
|
- lib/serega/errors.rb
|
27
25
|
- lib/serega/helpers/serializer_class_helper.rb
|
28
26
|
- lib/serega/json/adapter.rb
|
29
27
|
- lib/serega/json/json.rb
|
30
28
|
- lib/serega/json/oj.rb
|
31
29
|
- lib/serega/map.rb
|
30
|
+
- lib/serega/map_point.rb
|
31
|
+
- lib/serega/object_serializer.rb
|
32
32
|
- lib/serega/plugins.rb
|
33
33
|
- lib/serega/plugins/activerecord_preloads/activerecord_preloads.rb
|
34
34
|
- lib/serega/plugins/activerecord_preloads/lib/preloader.rb
|
35
|
+
- lib/serega/plugins/batch/batch.rb
|
36
|
+
- lib/serega/plugins/batch/lib/loader.rb
|
37
|
+
- lib/serega/plugins/batch/lib/loaders.rb
|
38
|
+
- lib/serega/plugins/batch/lib/plugins_extensions.rb
|
39
|
+
- lib/serega/plugins/batch/lib/validations/check_batch_opt_key.rb
|
40
|
+
- lib/serega/plugins/batch/lib/validations/check_batch_opt_loader.rb
|
41
|
+
- lib/serega/plugins/batch/lib/validations/check_opt_batch.rb
|
35
42
|
- lib/serega/plugins/context_metadata/context_metadata.rb
|
36
43
|
- lib/serega/plugins/formatters/formatters.rb
|
37
44
|
- lib/serega/plugins/hide_nil/hide_nil.rb
|
38
|
-
- lib/serega/plugins/lazy/lazy.rb
|
39
45
|
- lib/serega/plugins/metadata/meta_attribute.rb
|
40
46
|
- lib/serega/plugins/metadata/metadata.rb
|
41
47
|
- lib/serega/plugins/metadata/validations/check_block.rb
|
@@ -54,6 +60,7 @@ files:
|
|
54
60
|
- lib/serega/plugins/root/root.rb
|
55
61
|
- lib/serega/plugins/string_modifiers/parse_string_modifiers.rb
|
56
62
|
- lib/serega/plugins/string_modifiers/string_modifiers.rb
|
63
|
+
- lib/serega/serializer.rb
|
57
64
|
- lib/serega/utils/enum_deep_dup.rb
|
58
65
|
- lib/serega/utils/to_hash.rb
|
59
66
|
- lib/serega/validations/attribute/check_block.rb
|
data/lib/serega/convert.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Serega
|
4
|
-
class SeregaConvert
|
5
|
-
module SeregaConvertClassMethods
|
6
|
-
def call(object, **opts)
|
7
|
-
new(object, **opts).to_h
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
module SeregaConvertInstanceMethods
|
12
|
-
attr_reader :object, :opts
|
13
|
-
|
14
|
-
def initialize(object, **opts)
|
15
|
-
@object = object
|
16
|
-
@opts = opts
|
17
|
-
end
|
18
|
-
|
19
|
-
def to_h
|
20
|
-
many? ? many(object) : one(object) || {}
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def many(objects)
|
26
|
-
objects.map { |obj| one(obj) }
|
27
|
-
end
|
28
|
-
|
29
|
-
def one(object)
|
30
|
-
self.class.serializer_class::SeregaConvertItem.call(object, opts[:context], opts[:map])
|
31
|
-
end
|
32
|
-
|
33
|
-
def many?
|
34
|
-
many = opts[:many]
|
35
|
-
return many unless many.nil?
|
36
|
-
|
37
|
-
object.is_a?(Enumerable)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
extend Serega::SeregaHelpers::SerializerClassHelper
|
42
|
-
extend SeregaConvertClassMethods
|
43
|
-
include SeregaConvertInstanceMethods
|
44
|
-
end
|
45
|
-
end
|
data/lib/serega/convert_item.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Serega
|
4
|
-
class SeregaConvertItem
|
5
|
-
module SeregaConvertItemClassMethods
|
6
|
-
def call(object, context, map)
|
7
|
-
return unless object
|
8
|
-
|
9
|
-
map.each_with_object({}) do |(attribute, nested_attributes), hash|
|
10
|
-
value = attribute.value(object, context)
|
11
|
-
attach_value(value, hash, attribute, nested_attributes, context)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
def attach_value(value, hash, attribute, nested_attributes, context)
|
18
|
-
hash[attribute.name] =
|
19
|
-
if nested_attributes.empty?
|
20
|
-
attribute.relation? ? FROZEN_EMPTY_HASH : value
|
21
|
-
elsif many?(attribute, value)
|
22
|
-
value.map { |val| call(val, context, nested_attributes) }
|
23
|
-
else
|
24
|
-
call(value, context, nested_attributes)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def many?(attribute, object)
|
29
|
-
is_many = attribute.many
|
30
|
-
is_many.nil? ? object.is_a?(Enumerable) : is_many
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
extend Serega::SeregaHelpers::SerializerClassHelper
|
35
|
-
extend SeregaConvertItemClassMethods
|
36
|
-
end
|
37
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Serega
|
4
|
-
module SeregaPlugins
|
5
|
-
module Lazy
|
6
|
-
def self.plugin_name
|
7
|
-
:lazy
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.before_load_plugin(serializer_class, **opts)
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.load_plugin(serializer_class, **_opts)
|
14
|
-
serializer_class.extend(ClassMethods)
|
15
|
-
serializer_class.include(InstanceMethods)
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.after_load_plugin(serializer_class, **_opts)
|
19
|
-
serializer_class.config.attribute_keys << :lazy
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
module ClassMethods
|
24
|
-
def lazy(key:, buffer:, resolver:)
|
25
|
-
@lazy[key] = { buffer: buffer, resolver: resolver }
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
module InstanceMethods
|
30
|
-
def initialize(*args, **kwargs)
|
31
|
-
super
|
32
|
-
@lazy = {}
|
33
|
-
end
|
34
|
-
|
35
|
-
def to_h(*args, **kwargs)
|
36
|
-
result = super
|
37
|
-
lazy.each_key do |key, |
|
38
|
-
buffer = lazy.delete(key) # { val => [paths], val2 => [paths2] }
|
39
|
-
buffer_values = self.class.lazy[key][:resolver].(buffer.keys)
|
40
|
-
|
41
|
-
buffer_values.each do |key, resolved_value|
|
42
|
-
paths = buffer[key]
|
43
|
-
paths.each do |path|
|
44
|
-
result.dig(path[0, -2])
|
45
|
-
replace(result, buffer_values)
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
register_plugin(Metadata.plugin_name, Metadata)
|
52
|
-
end
|
53
|
-
end
|