serega 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/lib/serega/attribute.rb +2 -2
  4. data/lib/serega/config.rb +23 -1
  5. data/lib/serega/errors.rb +8 -5
  6. data/lib/serega/helpers/serializer_class_helper.rb +5 -0
  7. data/lib/serega/json/adapter.rb +6 -0
  8. data/lib/serega/json/json.rb +20 -0
  9. data/lib/serega/json/oj.rb +20 -0
  10. data/lib/serega/map.rb +17 -0
  11. data/lib/serega/map_point.rb +36 -1
  12. data/lib/serega/object_serializer.rb +17 -4
  13. data/lib/serega/plugins/activerecord_preloads/activerecord_preloads.rb +66 -18
  14. data/lib/serega/plugins/activerecord_preloads/lib/preloader.rb +100 -40
  15. data/lib/serega/plugins/batch/batch.rb +136 -10
  16. data/lib/serega/plugins/batch/lib/loader.rb +33 -1
  17. data/lib/serega/plugins/batch/lib/loaders.rb +15 -2
  18. data/lib/serega/plugins/batch/lib/plugins_extensions.rb +23 -1
  19. data/lib/serega/plugins/batch/lib/validations/check_batch_opt_key.rb +12 -0
  20. data/lib/serega/plugins/batch/lib/validations/check_batch_opt_loader.rb +12 -0
  21. data/lib/serega/plugins/batch/lib/validations/check_opt_batch.rb +12 -0
  22. data/lib/serega/plugins/context_metadata/context_metadata.rb +95 -13
  23. data/lib/serega/plugins/formatters/formatters.rb +94 -8
  24. data/lib/serega/plugins/hide_nil/hide_nil.rb +33 -7
  25. data/lib/serega/plugins/metadata/metadata.rb +108 -35
  26. data/lib/serega/plugins/metadata/validations/check_block.rb +3 -0
  27. data/lib/serega/plugins/metadata/validations/check_opt_hide_empty.rb +4 -1
  28. data/lib/serega/plugins/metadata/validations/check_opt_hide_nil.rb +4 -1
  29. data/lib/serega/plugins/metadata/validations/check_opts.rb +3 -0
  30. data/lib/serega/plugins/metadata/validations/check_path.rb +3 -0
  31. data/lib/serega/plugins/preloads/lib/enum_deep_freeze.rb +10 -1
  32. data/lib/serega/plugins/preloads/lib/format_user_preloads.rb +13 -4
  33. data/lib/serega/plugins/preloads/lib/main_preload_path.rb +16 -3
  34. data/lib/serega/plugins/preloads/lib/preloads_constructor.rb +4 -6
  35. data/lib/serega/plugins/preloads/preloads.rb +145 -12
  36. data/lib/serega/plugins/preloads/validations/check_opt_preload.rb +11 -0
  37. data/lib/serega/plugins/preloads/validations/check_opt_preload_path.rb +12 -0
  38. data/lib/serega/plugins/presenter/presenter.rb +20 -11
  39. data/lib/serega/plugins/root/root.rb +131 -19
  40. data/lib/serega/plugins/string_modifiers/parse_string_modifiers.rb +42 -12
  41. data/lib/serega/plugins/string_modifiers/string_modifiers.rb +14 -0
  42. data/lib/serega/plugins.rb +7 -1
  43. data/lib/serega/utils/enum_deep_dup.rb +5 -0
  44. data/lib/serega/utils/to_hash.rb +21 -3
  45. data/lib/serega/validations/attribute/check_block.rb +7 -2
  46. data/lib/serega/validations/attribute/check_name.rb +6 -0
  47. data/lib/serega/validations/attribute/check_opt_const.rb +12 -9
  48. data/lib/serega/validations/attribute/check_opt_delegate.rb +13 -10
  49. data/lib/serega/validations/attribute/check_opt_hide.rb +3 -0
  50. data/lib/serega/validations/attribute/check_opt_key.rb +12 -9
  51. data/lib/serega/validations/attribute/check_opt_many.rb +3 -0
  52. data/lib/serega/validations/attribute/check_opt_serializer.rb +3 -0
  53. data/lib/serega/validations/attribute/check_opt_value.rb +12 -9
  54. data/lib/serega/validations/check_attribute_params.rb +29 -1
  55. data/lib/serega/validations/check_initiate_params.rb +17 -0
  56. data/lib/serega/validations/check_serialize_params.rb +16 -0
  57. data/lib/serega/validations/initiate/check_modifiers.rb +15 -0
  58. data/lib/serega/validations/utils/check_allowed_keys.rb +14 -0
  59. data/lib/serega/validations/utils/check_opt_is_bool.rb +11 -0
  60. data/lib/serega/validations/utils/check_opt_is_hash.rb +11 -0
  61. data/lib/serega/validations/utils/check_opt_is_string_or_symbol.rb +11 -0
  62. data/lib/serega/version.rb +4 -0
  63. data/lib/serega.rb +83 -24
  64. metadata +2 -3
  65. 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
- module ClassMethods
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
- module ClassMethods
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
- def preload(object, preloads)
49
- Loader.call([object], preloads)
50
- object
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
- module ClassMethods
59
- def fit?(objects)
60
- objects.is_a?(ActiveRecord::Relation)
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
- def preload(objects, preloads)
64
- objects.load
65
- Loader.call(objects.to_a, preloads)
66
- objects
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
- module ClassMethods
75
- def fit?(objects)
76
- objects.is_a?(Array) &&
77
- ActiverecordObject.fit?(objects.first) &&
78
- same_kind?(objects)
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
- def preload(objects, preloads)
82
- Loader.call(objects, preloads)
83
- objects
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?(objects)
89
- first_object_class = objects.first.class
90
- objects.all? { |object| object.instance_of?(first_object_class) }
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
- module ClassMethods
99
- def fit?(objects)
100
- objects.is_a?(Enumerator) &&
101
- ActiverecordArray.fit?(objects.to_a)
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
- def preload(objects, preloads)
105
- ActiverecordArray.preload(objects.to_a, preloads)
106
- objects
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
- module SeregaSerializerInstanceMethods
156
- def initialize(**_args)
157
- super
158
- opts[:batch_loaders] = self.class.serializer_class::SeregaBatchLoaders.new
159
- end
272
+ #
273
+ # Serega additional/patched instance methods
274
+ #
275
+ # @see Serega
276
+ #
277
+ module InstanceMethods
278
+ private
160
279
 
161
- def serialize(*)
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
- attr_reader :object_serializer, :point
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
- def get(point, object_serializer)
9
- batch_loaders[point] ||= self.class.serializer_class::SeregaBatchLoader.new(object_serializer, point)
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.formatter_resolved
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