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