serega 0.11.1 → 0.12.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.
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)