serega 0.6.1 → 0.7.0
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/VERSION +1 -1
- data/lib/serega/attribute.rb +2 -2
- data/lib/serega/config.rb +23 -1
- data/lib/serega/errors.rb +8 -5
- data/lib/serega/helpers/serializer_class_helper.rb +5 -0
- data/lib/serega/json/adapter.rb +6 -0
- data/lib/serega/json/json.rb +20 -0
- data/lib/serega/json/oj.rb +20 -0
- data/lib/serega/map.rb +17 -0
- data/lib/serega/map_point.rb +36 -1
- data/lib/serega/object_serializer.rb +17 -4
- data/lib/serega/plugins/activerecord_preloads/activerecord_preloads.rb +66 -18
- data/lib/serega/plugins/activerecord_preloads/lib/preloader.rb +100 -40
- data/lib/serega/plugins/batch/batch.rb +136 -10
- data/lib/serega/plugins/batch/lib/loader.rb +33 -1
- data/lib/serega/plugins/batch/lib/loaders.rb +15 -2
- data/lib/serega/plugins/batch/lib/plugins_extensions.rb +23 -1
- data/lib/serega/plugins/batch/lib/validations/check_batch_opt_key.rb +12 -0
- data/lib/serega/plugins/batch/lib/validations/check_batch_opt_loader.rb +12 -0
- data/lib/serega/plugins/batch/lib/validations/check_opt_batch.rb +12 -0
- data/lib/serega/plugins/context_metadata/context_metadata.rb +95 -13
- data/lib/serega/plugins/formatters/formatters.rb +94 -8
- data/lib/serega/plugins/hide_nil/hide_nil.rb +33 -7
- data/lib/serega/plugins/metadata/metadata.rb +108 -35
- data/lib/serega/plugins/metadata/validations/check_block.rb +3 -0
- data/lib/serega/plugins/metadata/validations/check_opt_hide_empty.rb +4 -1
- data/lib/serega/plugins/metadata/validations/check_opt_hide_nil.rb +4 -1
- data/lib/serega/plugins/metadata/validations/check_opts.rb +3 -0
- data/lib/serega/plugins/metadata/validations/check_path.rb +3 -0
- data/lib/serega/plugins/preloads/lib/enum_deep_freeze.rb +10 -1
- data/lib/serega/plugins/preloads/lib/format_user_preloads.rb +13 -4
- data/lib/serega/plugins/preloads/lib/main_preload_path.rb +16 -3
- data/lib/serega/plugins/preloads/lib/preloads_constructor.rb +4 -6
- data/lib/serega/plugins/preloads/preloads.rb +145 -12
- data/lib/serega/plugins/preloads/validations/check_opt_preload.rb +11 -0
- data/lib/serega/plugins/preloads/validations/check_opt_preload_path.rb +12 -0
- data/lib/serega/plugins/presenter/presenter.rb +20 -11
- data/lib/serega/plugins/root/root.rb +131 -19
- data/lib/serega/plugins/string_modifiers/parse_string_modifiers.rb +42 -12
- data/lib/serega/plugins/string_modifiers/string_modifiers.rb +14 -0
- data/lib/serega/plugins.rb +7 -1
- data/lib/serega/utils/enum_deep_dup.rb +5 -0
- data/lib/serega/utils/to_hash.rb +21 -3
- data/lib/serega/validations/attribute/check_block.rb +7 -2
- data/lib/serega/validations/attribute/check_name.rb +6 -0
- data/lib/serega/validations/attribute/check_opt_const.rb +12 -9
- data/lib/serega/validations/attribute/check_opt_delegate.rb +13 -10
- data/lib/serega/validations/attribute/check_opt_hide.rb +3 -0
- data/lib/serega/validations/attribute/check_opt_key.rb +12 -9
- data/lib/serega/validations/attribute/check_opt_many.rb +3 -0
- data/lib/serega/validations/attribute/check_opt_serializer.rb +3 -0
- data/lib/serega/validations/attribute/check_opt_value.rb +12 -9
- data/lib/serega/validations/check_attribute_params.rb +29 -1
- data/lib/serega/validations/check_initiate_params.rb +17 -0
- data/lib/serega/validations/check_serialize_params.rb +16 -0
- data/lib/serega/validations/initiate/check_modifiers.rb +15 -0
- data/lib/serega/validations/utils/check_allowed_keys.rb +14 -0
- data/lib/serega/validations/utils/check_opt_is_bool.rb +11 -0
- data/lib/serega/validations/utils/check_opt_is_hash.rb +11 -0
- data/lib/serega/validations/utils/check_opt_is_string_or_symbol.rb +11 -0
- data/lib/serega/version.rb +4 -0
- data/lib/serega.rb +83 -24
- metadata +2 -3
- data/lib/serega/serializer.rb +0 -32
@@ -3,8 +3,16 @@
|
|
3
3
|
class Serega
|
4
4
|
module SeregaPlugins
|
5
5
|
module ActiverecordPreloads
|
6
|
+
# Handles preloads for different types of initial records
|
6
7
|
class Preloader
|
7
|
-
|
8
|
+
class << self
|
9
|
+
# Preloads associations to records
|
10
|
+
#
|
11
|
+
# @param object [Object] record(s)
|
12
|
+
# @param preloads [Hash] associations names
|
13
|
+
#
|
14
|
+
# @return [Object] provided object with preloaded associations
|
15
|
+
#
|
8
16
|
def preload(object, preloads)
|
9
17
|
return object if object.nil? || (object.is_a?(Array) && object.empty?) || preloads.empty?
|
10
18
|
|
@@ -14,6 +22,7 @@ class Serega
|
|
14
22
|
preload_handler.preload(object, preloads)
|
15
23
|
end
|
16
24
|
|
25
|
+
# @return [Array] Registered preload adapters for different types of initial records
|
17
26
|
def handlers
|
18
27
|
@handlers ||= [
|
19
28
|
ActiverecordRelation,
|
@@ -23,12 +32,19 @@ class Serega
|
|
23
32
|
].freeze
|
24
33
|
end
|
25
34
|
end
|
26
|
-
|
27
|
-
extend ClassMethods
|
28
35
|
end
|
29
36
|
|
37
|
+
# Associations loader for prepared records
|
30
38
|
class Loader
|
31
39
|
# :nocov: We can check only one version of activerecord
|
40
|
+
|
41
|
+
# Preloads associations to records
|
42
|
+
#
|
43
|
+
# @param records [Array<ActiveRecord::Base>] records
|
44
|
+
# @param associations [Hash] associations names
|
45
|
+
#
|
46
|
+
# @return [void]
|
47
|
+
#
|
32
48
|
def self.call(records, associations)
|
33
49
|
if ActiveRecord::VERSION::MAJOR >= 7
|
34
50
|
ActiveRecord::Associations::Preloader.new(records: records, associations: associations).call
|
@@ -39,75 +55,119 @@ class Serega
|
|
39
55
|
# :nocov:
|
40
56
|
end
|
41
57
|
|
58
|
+
# Preloader adapter for ActiveRecord object
|
42
59
|
class ActiverecordObject
|
43
|
-
|
60
|
+
class << self
|
61
|
+
#
|
62
|
+
# Checks object is kind of ActiveRecord::Base
|
63
|
+
#
|
64
|
+
# @param object [Object] object
|
65
|
+
#
|
66
|
+
# @return [Boolean] whether object is kind of ActiveRecord::Base
|
44
67
|
def fit?(object)
|
45
68
|
object.is_a?(ActiveRecord::Base)
|
46
69
|
end
|
47
70
|
|
48
|
-
|
49
|
-
|
50
|
-
|
71
|
+
#
|
72
|
+
# Preloads associations to ActiveRecord::Base record
|
73
|
+
#
|
74
|
+
# @param record [ActiveRecord::Base] record
|
75
|
+
#
|
76
|
+
# @return [Object] provided record with preloaded associations
|
77
|
+
def preload(record, preloads)
|
78
|
+
Loader.call([record], preloads)
|
79
|
+
record
|
51
80
|
end
|
52
81
|
end
|
53
|
-
|
54
|
-
extend ClassMethods
|
55
82
|
end
|
56
83
|
|
84
|
+
# Preloader adapter for ActiveRecord::Relation
|
57
85
|
class ActiverecordRelation
|
58
|
-
|
59
|
-
|
60
|
-
|
86
|
+
class << self
|
87
|
+
#
|
88
|
+
# Checks object is kind of ActiveRecord::Relation
|
89
|
+
#
|
90
|
+
# @param object [Object] object to check
|
91
|
+
#
|
92
|
+
# @return [Boolean] whether object is kind of ActiveRecord::Relation
|
93
|
+
def fit?(object)
|
94
|
+
object.is_a?(ActiveRecord::Relation)
|
61
95
|
end
|
62
96
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
97
|
+
#
|
98
|
+
# Preloads associations to ActiveRecord::Relation
|
99
|
+
#
|
100
|
+
# @param scope [ActiveRecord::Relation] scope
|
101
|
+
#
|
102
|
+
# @return [ActiveRecord::Relation] provided scope with preloaded associations
|
103
|
+
def preload(scope, preloads)
|
104
|
+
scope.load
|
105
|
+
Loader.call(scope.to_a, preloads)
|
106
|
+
scope
|
67
107
|
end
|
68
108
|
end
|
69
|
-
|
70
|
-
extend ClassMethods
|
71
109
|
end
|
72
110
|
|
111
|
+
# Preloader adapter for Array of ActiveRecord objects
|
73
112
|
class ActiverecordArray
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
113
|
+
class << self
|
114
|
+
#
|
115
|
+
# Checks object is an array of ActiveRecord::Base objects
|
116
|
+
#
|
117
|
+
# @param object [Object] object
|
118
|
+
#
|
119
|
+
# @return [Boolean] whether object is an array with ActiveRecord objects (and all objects have same class)
|
120
|
+
def fit?(object)
|
121
|
+
object.is_a?(Array) &&
|
122
|
+
ActiverecordObject.fit?(object.first) &&
|
123
|
+
same_kind?(object)
|
79
124
|
end
|
80
125
|
|
81
|
-
|
82
|
-
|
83
|
-
|
126
|
+
#
|
127
|
+
# Preloads associations to array with ActiveRecord::Base objects
|
128
|
+
#
|
129
|
+
# @param records [Array<ActiveRecord::Base>] ActiveRecord records
|
130
|
+
#
|
131
|
+
# @return [Array<ActiveRecord::Base>] provided records with preloaded associations
|
132
|
+
def preload(records, preloads)
|
133
|
+
Loader.call(records, preloads)
|
134
|
+
records
|
84
135
|
end
|
85
136
|
|
86
137
|
private
|
87
138
|
|
88
|
-
def same_kind?(
|
89
|
-
first_object_class =
|
90
|
-
|
139
|
+
def same_kind?(records)
|
140
|
+
first_object_class = records.first.class
|
141
|
+
records.all? { |record| record.instance_of?(first_object_class) }
|
91
142
|
end
|
92
143
|
end
|
93
|
-
|
94
|
-
extend ClassMethods
|
95
144
|
end
|
96
145
|
|
146
|
+
# Preloader adapter for Enumerator with ActiveRecord objects
|
97
147
|
class ActiverecordEnumerator
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
148
|
+
class << self
|
149
|
+
#
|
150
|
+
# Checks object is an Enumerator with each value is a ActiveRecord::Base object
|
151
|
+
#
|
152
|
+
# @param object [Object] object
|
153
|
+
#
|
154
|
+
# @return [Boolean] whether object is an Enumerator with each value is a ActiveRecord::Base object
|
155
|
+
def fit?(object)
|
156
|
+
object.is_a?(Enumerator) &&
|
157
|
+
ActiverecordArray.fit?(object.to_a)
|
102
158
|
end
|
103
159
|
|
104
|
-
|
105
|
-
|
106
|
-
|
160
|
+
#
|
161
|
+
# Preloads associations to Enumerator with ActiveRecord::Base objects
|
162
|
+
#
|
163
|
+
# @param enum [Enumerator<ActiveRecord::Base>] enum
|
164
|
+
#
|
165
|
+
# @return [Enumerator<ActiveRecord::Base>] provided enumerator with preloaded associations
|
166
|
+
def preload(enum, preloads)
|
167
|
+
ActiverecordArray.preload(enum.to_a, preloads)
|
168
|
+
enum
|
107
169
|
end
|
108
170
|
end
|
109
|
-
|
110
|
-
extend ClassMethods
|
111
171
|
end
|
112
172
|
end
|
113
173
|
end
|
@@ -2,11 +2,52 @@
|
|
2
2
|
|
3
3
|
class Serega
|
4
4
|
module SeregaPlugins
|
5
|
+
#
|
6
|
+
# Plugin that can be used to load attributes values in batches.
|
7
|
+
# Each batch loader accepts list of selected keys, context and current attribute point.
|
8
|
+
# Each batch loader must return Hash with values grouped by provided keys.
|
9
|
+
# There are specific `:default` option that can be used to add default value for missing key.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# class PostSerializer < Serega
|
13
|
+
# plugin :batch
|
14
|
+
#
|
15
|
+
# # Define batch loader via callable class, it must accept three args (keys, context, map_point)
|
16
|
+
# attribute :comments_count, batch: { key: :id, loader: PostCommentsCountBatchLoader, default: 0}
|
17
|
+
#
|
18
|
+
# # Define batch loader via Symbol, later we should define this loader via config.batch_loaders.define(:posts_comments_counter) { ... }
|
19
|
+
# attribute :comments_count, batch: { key: :id, loader: :posts_comments_counter, default: 0}
|
20
|
+
#
|
21
|
+
# # Define batch loader with serializer
|
22
|
+
# attribute :comments, serializer: CommentSerializer, batch: { key: :id, loader: :posts_comments, default: []}
|
23
|
+
#
|
24
|
+
# # Resulted block must return hash like { key => value(s) }
|
25
|
+
# config.batch_loaders.define(:posts_comments_counter) do |keys|
|
26
|
+
# Comment.group(:post_id).where(post_id: keys).count
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# # We can return objects that will be automatically serialized if attribute defined with :serializer
|
30
|
+
# # Parameter `context` can be used when loading batch
|
31
|
+
# # Parameter `map_point` can be used to find nested attributes that will be serialized (`map_point.preloads`)
|
32
|
+
# config.batch_loaders.define(:posts_comments) do |keys, context, map_point|
|
33
|
+
# Comment.where(post_id: keys).where(is_spam: false).group_by(&:post_id)
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
#
|
5
37
|
module Batch
|
38
|
+
# @return [Symbol] Plugin name
|
6
39
|
def self.plugin_name
|
7
40
|
:batch
|
8
41
|
end
|
9
42
|
|
43
|
+
#
|
44
|
+
# Applies plugin code to specific serializer
|
45
|
+
#
|
46
|
+
# @param serializer_class [Class<Serega>] Current serializer class
|
47
|
+
# @param _opts [Hash] Loaded plugins options
|
48
|
+
#
|
49
|
+
# @return [void]
|
50
|
+
#
|
10
51
|
def self.load_plugin(serializer_class, **_opts)
|
11
52
|
require_relative "./lib/loader"
|
12
53
|
require_relative "./lib/loaders"
|
@@ -15,13 +56,21 @@ class Serega
|
|
15
56
|
require_relative "./lib/validations/check_opt_batch"
|
16
57
|
|
17
58
|
serializer_class.extend(ClassMethods)
|
59
|
+
serializer_class.include(InstanceMethods)
|
18
60
|
serializer_class::CheckAttributeParams.include(CheckAttributeParamsInstanceMethods)
|
19
61
|
serializer_class::SeregaAttribute.include(AttributeInstanceMethods)
|
20
62
|
serializer_class::SeregaMapPoint.include(MapPointInstanceMethods)
|
21
|
-
serializer_class::SeregaSerializer.include(SeregaSerializerInstanceMethods)
|
22
63
|
serializer_class::SeregaObjectSerializer.include(SeregaObjectSerializerInstanceMethods)
|
23
64
|
end
|
24
65
|
|
66
|
+
#
|
67
|
+
# Runs callbacks after plugin was attached
|
68
|
+
#
|
69
|
+
# @param serializer_class [Class<Serega>] Current serializer class
|
70
|
+
# @param opts [Hash] loaded plugins opts
|
71
|
+
#
|
72
|
+
# @return [void]
|
73
|
+
#
|
25
74
|
def self.after_load_plugin(serializer_class, **opts)
|
26
75
|
config = serializer_class.config
|
27
76
|
config.attribute_keys << :batch
|
@@ -47,6 +96,9 @@ class Serega
|
|
47
96
|
end
|
48
97
|
end
|
49
98
|
|
99
|
+
#
|
100
|
+
# Batch loader config
|
101
|
+
#
|
50
102
|
class BatchLoadersConfig
|
51
103
|
attr_reader :opts
|
52
104
|
|
@@ -54,6 +106,15 @@ class Serega
|
|
54
106
|
@opts = opts
|
55
107
|
end
|
56
108
|
|
109
|
+
#
|
110
|
+
# Defines batch loader
|
111
|
+
#
|
112
|
+
# @param loader_name [Symbol] Batch loader name, that is used when defining attribute with batch loader.
|
113
|
+
# @param block [Proc] Block that can accept 3 parameters - keys, context, map_point
|
114
|
+
# and returns hash where ids are keys and values are batch loaded objects/
|
115
|
+
#
|
116
|
+
# @return [void]
|
117
|
+
#
|
57
118
|
def define(loader_name, &block)
|
58
119
|
unless block
|
59
120
|
raise SeregaError, "Block must be given to batch_loaders.define method"
|
@@ -67,20 +128,38 @@ class Serega
|
|
67
128
|
opts[loader_name] = block
|
68
129
|
end
|
69
130
|
|
131
|
+
#
|
132
|
+
# Finds previously defined batch loader by name
|
133
|
+
#
|
134
|
+
# @param loader_name [Symbol]
|
135
|
+
#
|
136
|
+
# @return [Proc] batch loader block
|
70
137
|
def fetch(loader_name)
|
71
138
|
opts[loader_name] || (raise SeregaError, "Batch loader with name `#{loader_name.inspect}` was not defined. Define example: config.batch_loaders.define(:#{loader_name}) { |keys, ctx, points| ... }")
|
72
139
|
end
|
73
140
|
end
|
74
141
|
|
142
|
+
#
|
143
|
+
# Stores batch config for specific attribute
|
144
|
+
#
|
75
145
|
class BatchModel
|
76
146
|
attr_reader :opts, :loaders, :many
|
77
147
|
|
148
|
+
#
|
149
|
+
# Initializes batch model
|
150
|
+
#
|
151
|
+
# @param opts [Hash] Attribute :batch option
|
152
|
+
# @param loaders [Array] Array of all loaders defined in serialize class
|
153
|
+
# @param many [Boolean] Option :many, defined on attribute
|
154
|
+
#
|
155
|
+
# @return [void]
|
78
156
|
def initialize(opts, loaders, many)
|
79
157
|
@opts = opts
|
80
158
|
@loaders = loaders
|
81
159
|
@many = many
|
82
160
|
end
|
83
161
|
|
162
|
+
# @return [#call] batch loader
|
84
163
|
def loader
|
85
164
|
@batch_loader ||= begin
|
86
165
|
loader = opts[:loader]
|
@@ -89,6 +168,7 @@ class Serega
|
|
89
168
|
end
|
90
169
|
end
|
91
170
|
|
171
|
+
# @return [Object] key (uid) of batch loaded object
|
92
172
|
def key
|
93
173
|
@batch_key ||= begin
|
94
174
|
key = opts[:key]
|
@@ -96,6 +176,7 @@ class Serega
|
|
96
176
|
end
|
97
177
|
end
|
98
178
|
|
179
|
+
# @return [Object] default value for missing key
|
99
180
|
def default_value
|
100
181
|
if opts.key?(:default)
|
101
182
|
opts[:default]
|
@@ -105,12 +186,25 @@ class Serega
|
|
105
186
|
end
|
106
187
|
end
|
107
188
|
|
189
|
+
#
|
190
|
+
# Config class additional/patched instance methods
|
191
|
+
#
|
192
|
+
# @see Serega::SeregaConfig
|
193
|
+
#
|
108
194
|
module ConfigInstanceMethods
|
195
|
+
#
|
196
|
+
# @return [Serega::SeregaPlugins::Batch::BatchLoadersConfig] configuration for batch loaders
|
197
|
+
#
|
109
198
|
def batch_loaders
|
110
199
|
@batch_loaders ||= BatchLoadersConfig.new(opts.fetch(:batch).fetch(:loaders))
|
111
200
|
end
|
112
201
|
end
|
113
202
|
|
203
|
+
#
|
204
|
+
# Serega class additional/patched class methods
|
205
|
+
#
|
206
|
+
# @see Serega::SeregaConfig
|
207
|
+
#
|
114
208
|
module ClassMethods
|
115
209
|
private
|
116
210
|
|
@@ -127,7 +221,14 @@ class Serega
|
|
127
221
|
end
|
128
222
|
end
|
129
223
|
|
224
|
+
#
|
225
|
+
# Serega::SeregaValidations::CheckAttributeParams additional/patched class methods
|
226
|
+
#
|
227
|
+
# @see Serega::SeregaValidations::CheckAttributeParams
|
228
|
+
#
|
130
229
|
module CheckAttributeParamsInstanceMethods
|
230
|
+
private
|
231
|
+
|
131
232
|
def check_opts
|
132
233
|
super
|
133
234
|
|
@@ -135,13 +236,29 @@ class Serega
|
|
135
236
|
end
|
136
237
|
end
|
137
238
|
|
239
|
+
#
|
240
|
+
# Serega::SeregaAttribute additional/patched class methods
|
241
|
+
#
|
242
|
+
# @see Serega::SeregaAttribute
|
243
|
+
#
|
138
244
|
module AttributeInstanceMethods
|
245
|
+
#
|
246
|
+
# @return [nil, Hash] :batch option
|
247
|
+
#
|
139
248
|
def batch
|
140
249
|
opts[:batch]
|
141
250
|
end
|
142
251
|
end
|
143
252
|
|
253
|
+
#
|
254
|
+
# Serega::SeregaMapPoint additional/patched class methods
|
255
|
+
#
|
256
|
+
# @see Serega::SeregaAttribute
|
257
|
+
#
|
144
258
|
module MapPointInstanceMethods
|
259
|
+
#
|
260
|
+
# @return [Serega::Batch::BatchModel] batch model that encapsulates everything needed to load current batch
|
261
|
+
#
|
145
262
|
def batch
|
146
263
|
return @batch if instance_variable_defined?(:@batch)
|
147
264
|
|
@@ -152,21 +269,30 @@ class Serega
|
|
152
269
|
end
|
153
270
|
end
|
154
271
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
272
|
+
#
|
273
|
+
# Serega additional/patched instance methods
|
274
|
+
#
|
275
|
+
# @see Serega
|
276
|
+
#
|
277
|
+
module InstanceMethods
|
278
|
+
private
|
160
279
|
|
161
|
-
|
280
|
+
#
|
281
|
+
# Loads batch loaded attributes after serialization
|
282
|
+
#
|
283
|
+
def serialize(object, opts)
|
284
|
+
batch_loaders = opts[:batch_loaders] = self.class::SeregaBatchLoaders.new
|
162
285
|
result = super
|
163
|
-
|
164
|
-
opts[:batch_loaders].load_all
|
165
|
-
|
286
|
+
batch_loaders.load_all
|
166
287
|
result
|
167
288
|
end
|
168
289
|
end
|
169
290
|
|
291
|
+
#
|
292
|
+
# SeregaObjectSerializer additional/patched class methods
|
293
|
+
#
|
294
|
+
# @see Serega::SeregaObjectSerializer
|
295
|
+
#
|
170
296
|
module SeregaObjectSerializerInstanceMethods
|
171
297
|
private
|
172
298
|
|
@@ -3,19 +3,51 @@
|
|
3
3
|
class Serega
|
4
4
|
module SeregaPlugins
|
5
5
|
module Batch
|
6
|
+
#
|
7
|
+
# Encapsulates point and according object_serializer
|
8
|
+
# so we can put batch loaded values to this serializer response
|
9
|
+
#
|
6
10
|
class SeregaBatchLoader
|
11
|
+
#
|
12
|
+
# Batch Loader instance methods
|
13
|
+
#
|
7
14
|
module InstanceMethods
|
8
|
-
|
15
|
+
# @return [Serega::SeregaMapPoint]
|
16
|
+
attr_reader :point
|
9
17
|
|
18
|
+
# @return [Serega::SeregaObjectSerializer]
|
19
|
+
attr_reader :object_serializer
|
20
|
+
|
21
|
+
#
|
22
|
+
# Initializes new SeregaBatchLoader
|
23
|
+
#
|
24
|
+
# @param object_serializer [Serega::SeregaObjectSerializer]
|
25
|
+
# @param point [Serega::SeregaMapPoint]
|
26
|
+
#
|
27
|
+
# @return [Serega::SeregaPlugins::Batch::SeregaBatchLoader]
|
28
|
+
#
|
10
29
|
def initialize(object_serializer, point)
|
11
30
|
@object_serializer = object_serializer
|
12
31
|
@point = point
|
13
32
|
end
|
14
33
|
|
34
|
+
#
|
35
|
+
# Remembers key and hash container where value for this key must be inserted
|
36
|
+
#
|
37
|
+
# @param key [Object] key that identifies batch loaded objects
|
38
|
+
# @param container [Hash] container where batch loaded objects must be attached
|
39
|
+
#
|
40
|
+
# @return [void]
|
41
|
+
#
|
15
42
|
def remember(key, container)
|
16
43
|
(keys[key] ||= []) << container
|
17
44
|
end
|
18
45
|
|
46
|
+
#
|
47
|
+
# Loads this batch and assigns values to remembered containers
|
48
|
+
#
|
49
|
+
# @return [void]
|
50
|
+
#
|
19
51
|
def load
|
20
52
|
keys_values = keys_values()
|
21
53
|
|
@@ -3,12 +3,25 @@
|
|
3
3
|
class Serega
|
4
4
|
module SeregaPlugins
|
5
5
|
module Batch
|
6
|
+
# Lists batch loaders registered during serialization
|
6
7
|
class SeregaBatchLoaders
|
8
|
+
# BatchLoaders instance methods
|
7
9
|
module InstanceMethods
|
8
|
-
|
9
|
-
|
10
|
+
#
|
11
|
+
# Initializes or fetches already initialized batch loader
|
12
|
+
#
|
13
|
+
# @param map_point [Serega::SeregaMapPoint] current map point
|
14
|
+
# @param object_serializer[Serega::SeregaObjectSerializer] current object serializer
|
15
|
+
#
|
16
|
+
# @return [Serega::SeregaPlugins::Batch::SeregaBatchLoader] Batch Loader
|
17
|
+
#
|
18
|
+
def get(map_point, object_serializer)
|
19
|
+
batch_loaders[map_point] ||= self.class.serializer_class::SeregaBatchLoader.new(object_serializer, map_point)
|
10
20
|
end
|
11
21
|
|
22
|
+
#
|
23
|
+
# Loads all registered batches and removes them from registered list
|
24
|
+
#
|
12
25
|
def load_all
|
13
26
|
return unless defined?(@batch_loaders)
|
14
27
|
|
@@ -3,9 +3,21 @@
|
|
3
3
|
class Serega
|
4
4
|
module SeregaPlugins
|
5
5
|
module Batch
|
6
|
+
# Extensions (mini-plugins) that are enabled when Batch plugin used with other plugins
|
6
7
|
module PluginsExtensions
|
8
|
+
#
|
9
|
+
# Extension that is used when batch plugin used with :active_record_preloads plugin
|
10
|
+
#
|
7
11
|
module ActiveRecordPreloads
|
12
|
+
#
|
13
|
+
# BatchLoader additional/patched instance methods
|
14
|
+
#
|
15
|
+
# @see Serega::SeregaPlugins::Batch::SeregaBatchLoader
|
16
|
+
#
|
8
17
|
module BatchLoaderInstanceMethods
|
18
|
+
private
|
19
|
+
|
20
|
+
# Preloads required associations to batch-loaded records
|
9
21
|
def keys_values(*)
|
10
22
|
data = super
|
11
23
|
|
@@ -21,13 +33,23 @@ class Serega
|
|
21
33
|
end
|
22
34
|
end
|
23
35
|
|
36
|
+
#
|
37
|
+
# Extension that is used when batch plugin used with :formatters plugin
|
38
|
+
#
|
24
39
|
module Formatters
|
40
|
+
#
|
41
|
+
# BatchLoader additional/patched instance methods
|
42
|
+
#
|
43
|
+
# @see Serega::SeregaPlugins::Batch::SeregaBatchLoader
|
44
|
+
#
|
25
45
|
module BatchLoaderInstanceMethods
|
46
|
+
private
|
47
|
+
|
26
48
|
# Format values after they are prepared
|
27
49
|
def keys_values(*)
|
28
50
|
data = super
|
29
51
|
|
30
|
-
formatter = point.attribute.
|
52
|
+
formatter = point.attribute.formatter
|
31
53
|
data.transform_values! { |value| formatter.call(value) } if formatter
|
32
54
|
|
33
55
|
data
|
@@ -3,8 +3,20 @@
|
|
3
3
|
class Serega
|
4
4
|
module SeregaPlugins
|
5
5
|
module Batch
|
6
|
+
#
|
7
|
+
# Validator for option :key in attribute :batch option
|
8
|
+
#
|
6
9
|
class CheckBatchOptKey
|
7
10
|
class << self
|
11
|
+
#
|
12
|
+
# Checks option :key of attribute :batch option
|
13
|
+
#
|
14
|
+
# @param key [nil, #call] Attribute :batch option :key
|
15
|
+
#
|
16
|
+
# @raise [SeregaError] validation error
|
17
|
+
#
|
18
|
+
# @return [void]
|
19
|
+
#
|
8
20
|
def call(key)
|
9
21
|
return if key.is_a?(Symbol)
|
10
22
|
|
@@ -3,8 +3,20 @@
|
|
3
3
|
class Serega
|
4
4
|
module SeregaPlugins
|
5
5
|
module Batch
|
6
|
+
#
|
7
|
+
# Validator for option :loader in attribute :batch option
|
8
|
+
#
|
6
9
|
class CheckBatchOptLoader
|
7
10
|
class << self
|
11
|
+
#
|
12
|
+
# Checks option :loader of attribute :batch option
|
13
|
+
#
|
14
|
+
# @param loader [nil, #call] Attribute :batch option :loader
|
15
|
+
#
|
16
|
+
# @raise [SeregaError] validation error
|
17
|
+
#
|
18
|
+
# @return [void]
|
19
|
+
#
|
8
20
|
def call(loader)
|
9
21
|
return if loader.is_a?(Symbol)
|
10
22
|
|
@@ -3,8 +3,20 @@
|
|
3
3
|
class Serega
|
4
4
|
module SeregaPlugins
|
5
5
|
module Batch
|
6
|
+
#
|
7
|
+
# Attribute `:batch` option validator
|
8
|
+
#
|
6
9
|
class CheckOptBatch
|
7
10
|
class << self
|
11
|
+
#
|
12
|
+
# Checks attribute :batch option
|
13
|
+
#
|
14
|
+
# @param opts [Hash] Attribute options
|
15
|
+
#
|
16
|
+
# @raise [SeregaError] Attribute validation error
|
17
|
+
#
|
18
|
+
# @return [void]
|
19
|
+
#
|
8
20
|
def call(opts, block)
|
9
21
|
return unless opts.key?(:batch)
|
10
22
|
|