serega 0.11.1 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +62 -13
  3. data/VERSION +1 -1
  4. data/lib/serega/attribute.rb +9 -4
  5. data/lib/serega/attribute_normalizer.rb +4 -13
  6. data/lib/serega/object_serializer.rb +11 -0
  7. data/lib/serega/plan.rb +20 -25
  8. data/lib/serega/plan_point.rb +13 -16
  9. data/lib/serega/plugins/batch/batch.rb +7 -245
  10. data/lib/serega/plugins/batch/lib/batch_config.rb +82 -0
  11. data/lib/serega/plugins/batch/lib/loader.rb +25 -7
  12. data/lib/serega/plugins/batch/lib/modules/attribute.rb +26 -0
  13. data/lib/serega/plugins/batch/lib/modules/attribute_normalizer.rb +65 -0
  14. data/lib/serega/plugins/batch/lib/modules/check_attribute_params.rb +22 -0
  15. data/lib/serega/plugins/batch/lib/modules/config.rb +23 -0
  16. data/lib/serega/plugins/batch/lib/modules/object_serializer.rb +46 -0
  17. data/lib/serega/plugins/batch/lib/modules/plan_point.rb +39 -0
  18. data/lib/serega/plugins/metadata/metadata.rb +5 -0
  19. data/lib/serega/plugins/preloads/lib/modules/attribute.rb +28 -0
  20. data/lib/serega/plugins/preloads/lib/modules/attribute_normalizer.rb +99 -0
  21. data/lib/serega/plugins/preloads/lib/modules/check_attribute_params.rb +22 -0
  22. data/lib/serega/plugins/preloads/lib/modules/config.rb +19 -0
  23. data/lib/serega/plugins/preloads/lib/modules/plan_point.rb +41 -0
  24. data/lib/serega/plugins/preloads/lib/preload_paths.rb +46 -0
  25. data/lib/serega/plugins/preloads/lib/preloads_config.rb +62 -0
  26. data/lib/serega/plugins/preloads/lib/preloads_constructor.rb +20 -7
  27. data/lib/serega/plugins/preloads/preloads.rb +12 -210
  28. data/lib/serega/plugins/preloads/validations/check_opt_preload_path.rb +54 -15
  29. metadata +16 -3
  30. data/lib/serega/plugins/preloads/lib/main_preload_path.rb +0 -53
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fe523bff250ef512761ea848c60d5cc5468742509a60e675bb089a666b95ad50
4
- data.tar.gz: 33c44df17578c3026d6b80d9c63152b4d4b238646b94feb93a849f2dd3b4d387
3
+ metadata.gz: 52535c7fab3897f65aec4e156ab5681e8595b4519df1e79a777688cee486a480
4
+ data.tar.gz: 16adbd9f036b0e23928049df873966f264db1004d2c4c1bc9e28422d687efd12
5
5
  SHA512:
6
- metadata.gz: 7f8041f6459fd5560f27c8f069c509df43c129ef87383227d7bee90ebad6489b4db983a5de4e7e7b767dabb22a02012fe8b1fba3cb21dd9963a0adadd444c756
7
- data.tar.gz: 55b4f299cad5da8f009fb0162ce2c558a0c01821db7318e7cf1d7ffc5915bdccfbc843ea924fe8fdcb5352897b1a871b4c8c829b8e585d3bfa6e03fe0a8c4abf
6
+ metadata.gz: 93a6aaefdf954556e31bd604ead1e376d5ffbb74225251e635bf5133af53da26f47e924f1f88349fa4656e228ddca573347d9f8fa15cc30bc6052f7e5dfec3bd
7
+ data.tar.gz: c84135d04c79aae1ccd03a3f3ac7dbed53dbf75165575afbb61ad6e32a558318cac2a8311c31b76df90fb74823facdf4677821d8f7ae8284f04782d33b04ad41
data/README.md CHANGED
@@ -415,30 +415,79 @@ UserSerializer.new(
415
415
  ```
416
416
 
417
417
  ---
418
- One tricky case, that you will probably never see in real life:
419
418
 
420
- Manually you can preload multiple associations, like this:
419
+ #### SPECIFIC CASE #1: Serializing same object as association
420
+
421
+ For example you decided to show your current user as "user" and "user_stats".
422
+ Where stats rely on user fields and some other associations.
423
+ You should specify `preload: nil` to preload nested associations, if any, to "user".
421
424
 
422
425
  ```ruby
423
- attribute :image,
424
- serializer: ImageSerializer,
425
- preload: { attachment: :blob },
426
- value: proc { |record| record.attachment }
426
+ class AppSerializer < Serega
427
+ plugin :preloads,
428
+ auto_preload_attributes_with_delegate: true,
429
+ auto_preload_attributes_with_serializer: true,
430
+ auto_hide_attributes_with_preload: true
431
+ end
432
+
433
+ class UserSerializer < AppSerializer
434
+ attribute :username
435
+ attribute :user_stats,
436
+ serializer: 'UserStatSerializer'
437
+ value: proc { |user| user },
438
+ preload: nil
439
+ end
427
440
  ```
428
441
 
429
- In this case we mark last element (in this case it will be `blob`) as main,
430
- so nested associations, if any, will be preloaded to this `blob`.
431
- If you need to preload them to `attachment`,
432
- please specify additionally `:preload_path` option like this:
442
+ #### SPECIFIC CASE #2: Serializing multiple associations as single relation
443
+
444
+ For example "user" has two relations - "new_profile", "old_profile", and also
445
+ profiles have "avatar" association. And you decided to serialize profiles in one
446
+ array. You can specify `preload_path: [[:new_profile], [:old_profile]]` to
447
+ achieve this:
448
+
449
+ ```ruby
450
+ class AppSerializer < Serega
451
+ plugin :preloads,
452
+ auto_preload_attributes_with_delegate: true,
453
+ auto_preload_attributes_with_serializer: true
454
+ end
455
+
456
+ class UserSerializer < AppSerializer
457
+ attribute :username
458
+ attribute :profiles,
459
+ serializer: 'ProfileSerializer',
460
+ value: proc { |user| [user.new_profile, user.old_profile] },
461
+ preload: [:new_profile, :old_profile],
462
+ preload_path: [[:new_profile], [:old_profile]] # <--- like here
463
+ end
464
+
465
+ class ProfileSerializer < AppSerializer
466
+ attribute :avatar, serializer: 'AvatarSerializer'
467
+ end
468
+
469
+ class AvatarSerializer < AppSerializer
470
+ end
471
+
472
+ UserSerializer.new.preloads
473
+ # => {:new_profile=>{:avatar=>{}}, :old_profile=>{:avatar=>{}}}
474
+ ```
475
+
476
+ #### SPECIFIC CASE #3: Preload association through another association
433
477
 
434
478
  ```ruby
435
479
  attribute :image,
480
+ preload: { attachment: :blob }, # <--------- like this one
481
+ value: proc { |record| record.attachment },
436
482
  serializer: ImageSerializer,
437
- preload: { attachment: :blob },
438
- preload_path: %i[attachment],
439
- value: proc { |record| record.attachment }
483
+ preload_path: [:attachment] # or preload_path: [:attachment, :blob]
440
484
  ```
441
485
 
486
+ In this case we don't know if preloads defined in ImageSerializer, should be
487
+ preloaded to `attachment` or `blob`, so please specify `preload_path` manually.
488
+ You can specify `preload_path: nil` if you are sure that there are no preloads
489
+ inside ImageSerializer.
490
+
442
491
  ---
443
492
 
444
493
  📌 Plugin `:preloads` only allows to group preloads together in single Hash, but
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.11.1
1
+ 0.12.0
@@ -82,13 +82,18 @@ class Serega
82
82
  #
83
83
  # Checks if attribute must be added to serialized response
84
84
  #
85
- # @param except [Hash] manually hidden attributes
86
- # @param only [Hash] manually enforced exposed attributes, other attributes are enforced to be hidden
87
- # @param with [Hash] manually enforced exposed attributes
85
+ # @param modifiers [Hash] Serialization modifiers
86
+ # @option modifiers [Hash] :only The only attributes to serialize
87
+ # @option modifiers [Hash] :except Attributes to hide
88
+ # @option modifiers [Hash] :with Hidden attributes to serialize additionally
88
89
  #
89
90
  # @return [Boolean]
90
91
  #
91
- def visible?(except:, only:, with:)
92
+ def visible?(modifiers)
93
+ except = modifiers[:except] || FROZEN_EMPTY_HASH
94
+ only = modifiers[:only] || FROZEN_EMPTY_HASH
95
+ with = modifiers[:with] || FROZEN_EMPTY_HASH
96
+
92
97
  return false if except.member?(name) && except[name].empty?
93
98
  return true if only.member?(name)
94
99
  return true if with.member?(name)
@@ -107,6 +107,7 @@ class Serega
107
107
  #
108
108
  # Patched in:
109
109
  # - plugin :preloads (returns true by default if config option auto_hide_attribute_with_preloads is enabled)
110
+ # - plugin :batch (returns true by default if auto_hide option was set and attribute has batch loader)
110
111
  #
111
112
  def prepare_hide
112
113
  init_opts[:hide]
@@ -135,7 +136,7 @@ class Serega
135
136
  def prepare_keyword_block
136
137
  key_method_name = key
137
138
  proc do |object|
138
- handle_no_method_error { object.public_send(key_method_name) }
139
+ object.public_send(key_method_name)
139
140
  end
140
141
  end
141
142
 
@@ -150,24 +151,14 @@ class Serega
150
151
 
151
152
  if allow_nil
152
153
  proc do |object|
153
- handle_no_method_error do
154
- object.public_send(delegate_to)&.public_send(key_method_name)
155
- end
154
+ object.public_send(delegate_to)&.public_send(key_method_name)
156
155
  end
157
156
  else
158
157
  proc do |object|
159
- handle_no_method_error do
160
- object.public_send(delegate_to).public_send(key_method_name)
161
- end
158
+ object.public_send(delegate_to).public_send(key_method_name)
162
159
  end
163
160
  end
164
161
  end
165
-
166
- def handle_no_method_error
167
- yield
168
- rescue NoMethodError => error
169
- raise error, "NoMethodError when serializing '#{name}' attribute in #{self.class.serializer_class}\n\n#{error.message}", error.backtrace
170
- end
171
162
  end
172
163
 
173
164
  extend Serega::SeregaHelpers::SerializerClassHelper
@@ -47,6 +47,10 @@ class Serega
47
47
  def serialize_object(object)
48
48
  plan.points.each_with_object({}) do |point, container|
49
49
  serialize_point(object, point, container)
50
+ rescue SeregaError
51
+ raise
52
+ rescue => error
53
+ reraise_with_serialized_attribute_details(error, point)
50
54
  end
51
55
  end
52
56
 
@@ -85,6 +89,13 @@ class Serega
85
89
  def array?(object, many)
86
90
  many.nil? ? object.is_a?(Enumerable) : many
87
91
  end
92
+
93
+ def reraise_with_serialized_attribute_details(error, point)
94
+ raise error.exception(<<~MESSAGE.strip)
95
+ #{error.message}
96
+ (when serializing '#{point.name}' attribute in #{self.class.serializer_class})
97
+ MESSAGE
98
+ end
88
99
  end
89
100
 
90
101
  extend Serega::SeregaHelpers::SerializerClassHelper
data/lib/serega/plan.rb CHANGED
@@ -22,34 +22,22 @@ class Serega
22
22
  #
23
23
  def call(opts)
24
24
  max_cache_size = serializer_class.config.max_cached_plans_per_serializer_count
25
- return plan_for(opts) if max_cache_size.zero?
25
+ return new(opts) if max_cache_size.zero?
26
26
 
27
27
  cached_plan_for(opts, max_cache_size)
28
28
  end
29
29
 
30
30
  private
31
31
 
32
- def plan_for(opts)
33
- new(**modifiers(opts))
34
- end
35
-
36
32
  def cached_plan_for(opts, max_cache_size)
37
33
  @cache ||= {}
38
34
  cache_key = construct_cache_key(opts)
39
35
 
40
- plan = @cache[cache_key] ||= plan_for(opts)
36
+ plan = @cache[cache_key] ||= new(opts)
41
37
  @cache.shift if @cache.length > max_cache_size
42
38
  plan
43
39
  end
44
40
 
45
- def modifiers(opts)
46
- {
47
- only: opts[:only] || FROZEN_EMPTY_HASH,
48
- except: opts[:except] || FROZEN_EMPTY_HASH,
49
- with: opts[:with] || FROZEN_EMPTY_HASH
50
- }
51
- end
52
-
53
41
  def construct_cache_key(opts, cache_key = nil)
54
42
  return nil if opts.empty?
55
43
 
@@ -69,10 +57,14 @@ class Serega
69
57
  # SeregaPlan instance methods
70
58
  #
71
59
  module InstanceMethods
72
- # Parent plan point, if exists
60
+ # Parent plan point
73
61
  # @return [SeregaPlanPoint, nil]
74
62
  attr_reader :parent_plan_point
75
63
 
64
+ # Sets new parent plan point
65
+ # @return [SeregaPlanPoint] new parent plan point
66
+ attr_writer :parent_plan_point
67
+
76
68
  # Serialization points
77
69
  # @return [Array<SeregaPlanPoint>] points to serialize
78
70
  attr_reader :points
@@ -80,17 +72,15 @@ class Serega
80
72
  #
81
73
  # Instantiate new serialization plan.
82
74
  #
83
- # @param opts Serialization parameters
84
- # @option opts [Hash] :only The only attributes to serialize
85
- # @option opts [Hash] :except Attributes to hide
86
- # @option opts [Hash] :with Attributes (usually marked hide: true`) to serialize additionally
87
- # @option opts [Hash] :with Attributes (usually marked hide: true`) to serialize additionally
75
+ # @param modifiers Serialization parameters
76
+ # @option modifiers [Hash] :only The only attributes to serialize
77
+ # @option modifiers [Hash] :except Attributes to hide
78
+ # @option modifiers [Hash] :with Hidden attributes to serialize additionally
88
79
  #
89
80
  # @return [SeregaPlan] Serialization plan
90
81
  #
91
- def initialize(only:, except:, with:, parent_plan_point: nil)
92
- @parent_plan_point = parent_plan_point
93
- @points = attributes_points(only: only, except: except, with: with)
82
+ def initialize(modifiers)
83
+ @points = attributes_points(modifiers)
94
84
  end
95
85
 
96
86
  #
@@ -102,7 +92,10 @@ class Serega
102
92
 
103
93
  private
104
94
 
105
- def attributes_points(only:, except:, with:)
95
+ def attributes_points(modifiers)
96
+ only = modifiers[:only] || FROZEN_EMPTY_HASH
97
+ except = modifiers[:except] || FROZEN_EMPTY_HASH
98
+ with = modifiers[:with] || FROZEN_EMPTY_HASH
106
99
  points = []
107
100
 
108
101
  serializer_class.attributes.each_value do |attribute|
@@ -114,7 +107,9 @@ class Serega
114
107
  {only: only[name], with: with[name], except: except[name]}
115
108
  end
116
109
 
117
- points << serializer_class::SeregaPlanPoint.new(attribute, self, child_fields)
110
+ point = serializer_class::SeregaPlanPoint.new(attribute, child_fields)
111
+ point.plan = self
112
+ points << point.freeze
118
113
  end
119
114
 
120
115
  points.freeze
@@ -13,7 +13,7 @@ class Serega
13
13
 
14
14
  # Link to current plan this point belongs to
15
15
  # @return [SeregaAttribute] Current plan
16
- attr_reader :plan
16
+ attr_accessor :plan
17
17
 
18
18
  # Shows current attribute
19
19
  # @return [SeregaAttribute] Current attribute
@@ -24,8 +24,8 @@ class Serega
24
24
  attr_reader :child_plan
25
25
 
26
26
  # Child fields to serialize
27
- # @return [SeregaPlan, nil] Attribute serialization plan
28
- attr_reader :child_fields
27
+ # @return [Hash] Attributes to serialize
28
+ attr_reader :modifiers
29
29
 
30
30
  # @!method name
31
31
  # Attribute `name`
@@ -44,18 +44,18 @@ class Serega
44
44
  #
45
45
  # Initializes plan point
46
46
  #
47
- # @param plan [SeregaPlan] Plan where this point belongs to.
48
47
  # @param attribute [SeregaAttribute] Attribute to construct plan point
49
- # @param child_fields [Hash, nil] Child fields (:only, :with, :except)
48
+ # @param modifiers Serialization parameters
49
+ # @option modifiers [Hash] :only The only attributes to serialize
50
+ # @option modifiers [Hash] :except Attributes to hide
51
+ # @option modifiers [Hash] :with Hidden attributes to serialize additionally
50
52
  #
51
53
  # @return [SeregaPlanPoint] New plan point
52
54
  #
53
- def initialize(attribute, plan = nil, child_fields = nil)
54
- @plan = plan
55
+ def initialize(attribute, modifiers = nil)
55
56
  @attribute = attribute
56
- @child_fields = child_fields
57
+ @modifiers = modifiers
57
58
  set_normalized_vars
58
- freeze
59
59
  end
60
60
 
61
61
  #
@@ -77,14 +77,11 @@ class Serega
77
77
  def prepare_child_plan
78
78
  return unless serializer
79
79
 
80
- fields = child_fields || FROZEN_EMPTY_HASH
80
+ fields = modifiers || FROZEN_EMPTY_HASH
81
81
 
82
- serializer::SeregaPlan.new(
83
- parent_plan_point: self,
84
- only: fields[:only] || FROZEN_EMPTY_HASH,
85
- with: fields[:with] || FROZEN_EMPTY_HASH,
86
- except: fields[:except] || FROZEN_EMPTY_HASH
87
- )
82
+ plan = serializer::SeregaPlan.new(fields)
83
+ plan.parent_plan_point = self
84
+ plan
88
85
  end
89
86
  end
90
87
 
@@ -79,8 +79,15 @@ class Serega
79
79
  # @return [void]
80
80
  #
81
81
  def self.load_plugin(serializer_class, **_opts)
82
+ require_relative "./lib/batch_config"
82
83
  require_relative "./lib/loader"
83
84
  require_relative "./lib/loaders"
85
+ require_relative "./lib/modules/attribute"
86
+ require_relative "./lib/modules/attribute_normalizer"
87
+ require_relative "./lib/modules/check_attribute_params"
88
+ require_relative "./lib/modules/config"
89
+ require_relative "./lib/modules/object_serializer"
90
+ require_relative "./lib/modules/plan_point"
84
91
  require_relative "./lib/validations/check_batch_opt_key"
85
92
  require_relative "./lib/validations/check_batch_opt_loader"
86
93
  require_relative "./lib/validations/check_opt_batch"
@@ -136,97 +143,6 @@ class Serega
136
143
  config.batch.default_key = opts[:default_key] if opts.key?(:default_key)
137
144
  end
138
145
 
139
- #
140
- # Batch loader config
141
- #
142
- class BatchConfig
143
- attr_reader :opts
144
-
145
- def initialize(opts)
146
- @opts = opts
147
- end
148
-
149
- #
150
- # Defines batch loader
151
- #
152
- # @param loader_name [Symbol] Batch loader name, that is used when defining attribute with batch loader.
153
- # @param block [Proc] Block that can accept 3 parameters - keys, context, plan_point
154
- # and returns hash where ids are keys and values are batch loaded objects/
155
- #
156
- # @return [void]
157
- #
158
- def define(loader_name, &block)
159
- unless block
160
- raise SeregaError, "Block must be given to #define method"
161
- end
162
-
163
- params = block.parameters
164
- if params.count > 3 || !params.all? { |param| (param[0] == :req) || (param[0] == :opt) }
165
- raise SeregaError, "Block can have maximum 3 regular parameters"
166
- end
167
-
168
- loaders[loader_name] = block
169
- end
170
-
171
- # Shows defined loaders
172
- # @return [Hash] defined loaders
173
- def loaders
174
- opts[:loaders]
175
- end
176
-
177
- #
178
- # Finds previously defined batch loader by name
179
- #
180
- # @param loader_name [Symbol]
181
- #
182
- # @return [Proc] batch loader block
183
- def fetch_loader(loader_name)
184
- loaders[loader_name] || (raise SeregaError, "Batch loader with name `#{loader_name.inspect}` was not defined. Define example: config.batch.define(:#{loader_name}) { |keys, ctx, points| ... }")
185
- end
186
-
187
- # Shows option to auto hide attributes with :batch specified
188
- # @return [Boolean, nil] option value
189
- def auto_hide
190
- opts[:auto_hide]
191
- end
192
-
193
- # @param value [Boolean] New :auto_hide option value
194
- # @return [Boolean] New option value
195
- def auto_hide=(value)
196
- raise SeregaError, "Must have boolean value, #{value.inspect} provided" if (value != true) && (value != false)
197
- opts[:auto_hide] = value
198
- end
199
-
200
- # Shows default key for :batch option
201
- # @return [Symbol, nil] default key for :batch option
202
- def default_key
203
- opts[:default_key]
204
- end
205
-
206
- # @param value [Symbol] New :default_key option value
207
- # @return [Boolean] New option value
208
- def default_key=(value)
209
- raise SeregaError, "Must be a Symbol, #{value.inspect} provided" unless value.is_a?(Symbol)
210
- opts[:default_key] = value
211
- end
212
- end
213
-
214
- #
215
- # Config class additional/patched instance methods
216
- #
217
- # @see Serega::SeregaConfig
218
- #
219
- module ConfigInstanceMethods
220
- #
221
- # Returns all batch loaders registered for current serializer
222
- #
223
- # @return [Serega::SeregaPlugins::Batch::BatchConfig] configuration for batch loaded attributes
224
- #
225
- def batch
226
- @batch ||= BatchConfig.new(opts.fetch(:batch))
227
- end
228
- end
229
-
230
146
  #
231
147
  # Serega class additional/patched class methods
232
148
  #
@@ -248,138 +164,6 @@ class Serega
248
164
  end
249
165
  end
250
166
 
251
- #
252
- # Serega::SeregaValidations::CheckAttributeParams additional/patched class methods
253
- #
254
- # @see Serega::SeregaValidations::CheckAttributeParams
255
- #
256
- module CheckAttributeParamsInstanceMethods
257
- private
258
-
259
- def check_opts
260
- super
261
-
262
- CheckOptBatch.call(opts, block, self.class.serializer_class)
263
- end
264
- end
265
-
266
- #
267
- # Serega::SeregaAttribute additional/patched class methods
268
- #
269
- # @see Serega::SeregaAttribute
270
- #
271
- module AttributeInstanceMethods
272
- #
273
- # @return [nil, Hash] :batch option
274
- #
275
- attr_reader :batch
276
-
277
- private
278
-
279
- def set_normalized_vars(normalizer)
280
- super
281
- @batch = normalizer.batch
282
- end
283
- end
284
-
285
- #
286
- # SeregaAttributeNormalizer additional/patched instance methods
287
- #
288
- # @see SeregaAttributeNormalizer::AttributeInstanceMethods
289
- #
290
- module AttributeNormalizerInstanceMethods
291
- #
292
- # Returns normalized attribute :batch option with prepared :key and
293
- # :default options. Option :loader will be prepared at serialization
294
- # time as loaders are usually defined after attributes.
295
- #
296
- # @return [Hash] attribute :batch normalized options
297
- #
298
- def batch
299
- return @batch if instance_variable_defined?(:@batch)
300
-
301
- @batch = prepare_batch
302
- end
303
-
304
- private
305
-
306
- #
307
- # Patch for original `prepare_hide` method
308
- #
309
- # Marks attribute hidden if auto_hide option was set and attribute has batch loader
310
- #
311
- def prepare_hide
312
- res = super
313
- return res unless res.nil?
314
-
315
- if batch
316
- self.class.serializer_class.config.batch.auto_hide || nil
317
- end
318
- end
319
-
320
- def prepare_batch
321
- batch = init_opts[:batch]
322
- return unless batch
323
-
324
- # take loader
325
- loader = batch[:loader]
326
-
327
- # take key
328
- key = batch[:key] || self.class.serializer_class.config.batch.default_key
329
- proc_key =
330
- if key.is_a?(Symbol)
331
- proc do |object|
332
- handle_no_method_error { object.public_send(key) }
333
- end
334
- else
335
- key
336
- end
337
-
338
- # take default value
339
- default = batch.fetch(:default) { many ? FROZEN_EMPTY_ARRAY : nil }
340
-
341
- {loader: loader, key: proc_key, default: default}
342
- end
343
-
344
- def handle_no_method_error
345
- yield
346
- rescue NoMethodError => error
347
- raise error, "NoMethodError when serializing '#{name}' attribute in #{self.class.serializer_class}\n\n#{error.message}", error.backtrace
348
- end
349
- end
350
-
351
- #
352
- # Serega::SeregaPlanPoint additional/patched class methods
353
- #
354
- # @see SeregaAttribute
355
- #
356
- module PlanPointInstanceMethods
357
- #
358
- # Returns attribute :batch option with prepared loader
359
- # @return [Hash] attribute :batch option
360
- #
361
- attr_reader :batch
362
-
363
- private
364
-
365
- def set_normalized_vars
366
- super
367
- @batch = prepare_batch
368
- end
369
-
370
- def prepare_batch
371
- batch = attribute.batch
372
- if batch
373
- loader = batch[:loader]
374
- if loader.is_a?(Symbol)
375
- batch_config = attribute.class.serializer_class.config.batch
376
- batch[:loader] = batch_config.fetch_loader(loader)
377
- end
378
- end
379
- batch
380
- end
381
- end
382
-
383
167
  #
384
168
  # Serega additional/patched instance methods
385
169
  #
@@ -398,28 +182,6 @@ class Serega
398
182
  result
399
183
  end
400
184
  end
401
-
402
- #
403
- # SeregaObjectSerializer additional/patched class methods
404
- #
405
- # @see Serega::SeregaObjectSerializer
406
- #
407
- module SeregaObjectSerializerInstanceMethods
408
- private
409
-
410
- def attach_value(object, point, container)
411
- batch = point.batch
412
- return super unless batch
413
-
414
- remember_key_for_batch_loading(batch, object, point, container)
415
- end
416
-
417
- def remember_key_for_batch_loading(batch, object, point, container)
418
- key = batch[:key].call(object, context)
419
- opts[:batch_loaders].get(point, self).remember(key, container)
420
- container[point.name] = nil # Reserve attribute place in resulted hash. We will set correct value later
421
- end
422
- end
423
185
  end
424
186
 
425
187
  register_plugin(Batch.plugin_name, Batch)