serega 0.20.1 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +113 -226
- data/VERSION +1 -1
- data/lib/serega/attribute.rb +31 -3
- data/lib/serega/attribute_normalizer.rb +143 -42
- data/lib/serega/batch/attribute_loader.rb +70 -0
- data/lib/serega/batch/attribute_loaders.rb +59 -0
- data/lib/serega/batch/auto_resolver.rb +24 -0
- data/lib/serega/batch/auto_resolver_factory.rb +48 -0
- data/lib/serega/batch/loader.rb +67 -0
- data/lib/serega/config.rb +59 -1
- data/lib/serega/object_serializer.rb +11 -9
- data/lib/serega/plan.rb +16 -0
- data/lib/serega/plan_point.rb +31 -5
- data/lib/serega/plugins/activerecord_preloads/activerecord_preloads.rb +42 -23
- data/lib/serega/plugins/activerecord_preloads/lib/active_record_objects.rb +31 -0
- data/lib/serega/plugins/camel_case/camel_case.rb +1 -1
- data/lib/serega/plugins/formatters/formatters.rb +79 -22
- data/lib/serega/plugins/if/if.rb +41 -22
- data/lib/serega/plugins/if/validations/check_opt_if.rb +27 -6
- data/lib/serega/plugins/if/validations/check_opt_if_value.rb +27 -6
- data/lib/serega/plugins/if/validations/check_opt_unless.rb +27 -6
- data/lib/serega/plugins/if/validations/check_opt_unless_value.rb +27 -6
- data/lib/serega/plugins/metadata/meta_attribute.rb +9 -10
- data/lib/serega/plugins/metadata/validations/check_block.rb +2 -4
- data/lib/serega/plugins/metadata/validations/check_opt_value.rb +2 -3
- data/lib/serega/plugins/presenter/presenter.rb +1 -1
- data/lib/serega/plugins/string_modifiers/parse_string_modifiers.rb +43 -30
- data/lib/serega/utils/format_user_preloads.rb +58 -0
- data/lib/serega/utils/method_signature.rb +89 -0
- data/lib/serega/utils/preload_paths.rb +53 -0
- data/lib/serega/utils/preloads_constructor.rb +77 -0
- data/lib/serega/validations/attribute/check_block.rb +38 -6
- data/lib/serega/validations/attribute/check_opt_batch.rb +101 -0
- data/lib/serega/validations/attribute/check_opt_const.rb +1 -0
- data/lib/serega/validations/attribute/check_opt_delegate.rb +1 -0
- data/lib/serega/validations/attribute/check_opt_method.rb +1 -0
- data/lib/serega/{plugins/preloads/validations → validations/attribute}/check_opt_preload.rb +2 -2
- data/lib/serega/{plugins/preloads/validations → validations/attribute}/check_opt_preload_path.rb +3 -3
- data/lib/serega/validations/attribute/check_opt_value.rb +35 -9
- data/lib/serega/validations/check_attribute_params.rb +3 -2
- data/lib/serega/validations/check_batch_loader_params.rb +80 -0
- data/lib/serega/validations/initiate/check_modifiers.rb +1 -1
- data/lib/serega.rb +110 -11
- metadata +17 -37
- data/lib/serega/plugins/batch/batch.rb +0 -168
- data/lib/serega/plugins/batch/lib/batch_config.rb +0 -77
- data/lib/serega/plugins/batch/lib/loader.rb +0 -113
- data/lib/serega/plugins/batch/lib/loaders.rb +0 -45
- data/lib/serega/plugins/batch/lib/modules/attribute.rb +0 -26
- data/lib/serega/plugins/batch/lib/modules/attribute_normalizer.rb +0 -78
- data/lib/serega/plugins/batch/lib/modules/check_attribute_params.rb +0 -22
- data/lib/serega/plugins/batch/lib/modules/config.rb +0 -23
- data/lib/serega/plugins/batch/lib/modules/object_serializer.rb +0 -46
- data/lib/serega/plugins/batch/lib/modules/plan_point.rb +0 -22
- data/lib/serega/plugins/batch/lib/plugins_extensions/activerecord_preloads.rb +0 -43
- data/lib/serega/plugins/batch/lib/plugins_extensions/formatters.rb +0 -54
- data/lib/serega/plugins/batch/lib/plugins_extensions/if.rb +0 -31
- data/lib/serega/plugins/batch/lib/plugins_extensions/preloads.rb +0 -34
- data/lib/serega/plugins/batch/lib/validations/check_batch_opt_id_method.rb +0 -43
- data/lib/serega/plugins/batch/lib/validations/check_batch_opt_loader.rb +0 -59
- data/lib/serega/plugins/batch/lib/validations/check_opt_batch.rb +0 -62
- data/lib/serega/plugins/preloads/lib/format_user_preloads.rb +0 -60
- data/lib/serega/plugins/preloads/lib/modules/attribute.rb +0 -28
- data/lib/serega/plugins/preloads/lib/modules/attribute_normalizer.rb +0 -99
- data/lib/serega/plugins/preloads/lib/modules/check_attribute_params.rb +0 -22
- data/lib/serega/plugins/preloads/lib/modules/config.rb +0 -19
- data/lib/serega/plugins/preloads/lib/modules/plan_point.rb +0 -41
- data/lib/serega/plugins/preloads/lib/preload_paths.rb +0 -53
- data/lib/serega/plugins/preloads/lib/preloads_config.rb +0 -62
- data/lib/serega/plugins/preloads/lib/preloads_constructor.rb +0 -79
- data/lib/serega/plugins/preloads/preloads.rb +0 -162
- data/lib/serega/utils/params_count.rb +0 -50
- data/lib/serega/validations/utils/check_extra_keyword_arg.rb +0 -33
@@ -1,168 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Serega
|
4
|
-
module SeregaPlugins
|
5
|
-
#
|
6
|
-
# Plugin `:batch`
|
7
|
-
#
|
8
|
-
# Must be used to omit N+1 when loading attributes values.
|
9
|
-
#
|
10
|
-
# @example Quick example
|
11
|
-
#
|
12
|
-
# class AppSerializer
|
13
|
-
# plugin :batch, id_method: :id
|
14
|
-
# end
|
15
|
-
#
|
16
|
-
# class UserSerializer < AppSerializer
|
17
|
-
# attribute :comments_count, batch: { loader: CommentsCountBatchLoader }, default: 0
|
18
|
-
# attribute :company, serializer: CompanySerializer, batch: { loader: UserCompanyBatchLoader }
|
19
|
-
# end
|
20
|
-
#
|
21
|
-
module Batch
|
22
|
-
# Returns plugin name
|
23
|
-
# @return [Symbol] Plugin name
|
24
|
-
def self.plugin_name
|
25
|
-
:batch
|
26
|
-
end
|
27
|
-
|
28
|
-
# Checks requirements to load plugin
|
29
|
-
#
|
30
|
-
# @param serializer_class [Class<Serega>] Current serializer class
|
31
|
-
# @param opts [Hash] plugin options
|
32
|
-
#
|
33
|
-
# @return [void]
|
34
|
-
#
|
35
|
-
def self.before_load_plugin(serializer_class, **opts)
|
36
|
-
allowed_keys = %i[auto_hide id_method]
|
37
|
-
opts.each_key do |key|
|
38
|
-
next if allowed_keys.include?(key)
|
39
|
-
|
40
|
-
raise SeregaError,
|
41
|
-
"Plugin #{plugin_name.inspect} does not accept the #{key.inspect} option. Allowed options:\n" \
|
42
|
-
" - :auto_hide [Boolean] - Marks attribute as hidden when it has :batch loader specified\n" \
|
43
|
-
" - :id_method [Symbol, #call] - Specified the default method to use to find object identifier"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
#
|
48
|
-
# Applies plugin code to specific serializer
|
49
|
-
#
|
50
|
-
# @param serializer_class [Class<Serega>] Current serializer class
|
51
|
-
# @param _opts [Hash] Plugin options
|
52
|
-
#
|
53
|
-
# @return [void]
|
54
|
-
#
|
55
|
-
def self.load_plugin(serializer_class, **_opts)
|
56
|
-
require_relative "lib/batch_config"
|
57
|
-
require_relative "lib/loader"
|
58
|
-
require_relative "lib/loaders"
|
59
|
-
require_relative "lib/modules/attribute"
|
60
|
-
require_relative "lib/modules/attribute_normalizer"
|
61
|
-
require_relative "lib/modules/check_attribute_params"
|
62
|
-
require_relative "lib/modules/config"
|
63
|
-
require_relative "lib/modules/object_serializer"
|
64
|
-
require_relative "lib/modules/plan_point"
|
65
|
-
require_relative "lib/validations/check_batch_opt_id_method"
|
66
|
-
require_relative "lib/validations/check_batch_opt_loader"
|
67
|
-
require_relative "lib/validations/check_opt_batch"
|
68
|
-
|
69
|
-
serializer_class.extend(ClassMethods)
|
70
|
-
serializer_class.include(InstanceMethods)
|
71
|
-
serializer_class::CheckAttributeParams.include(CheckAttributeParamsInstanceMethods)
|
72
|
-
serializer_class::SeregaAttribute.include(AttributeInstanceMethods)
|
73
|
-
serializer_class::SeregaAttributeNormalizer.include(AttributeNormalizerInstanceMethods)
|
74
|
-
serializer_class::SeregaPlanPoint.include(PlanPointInstanceMethods)
|
75
|
-
serializer_class::SeregaObjectSerializer.include(SeregaObjectSerializerInstanceMethods)
|
76
|
-
end
|
77
|
-
|
78
|
-
#
|
79
|
-
# Runs callbacks after plugin was attached
|
80
|
-
#
|
81
|
-
# @param serializer_class [Class<Serega>] Current serializer class
|
82
|
-
# @param opts [Hash] Plugin options
|
83
|
-
#
|
84
|
-
# @return [void]
|
85
|
-
#
|
86
|
-
def self.after_load_plugin(serializer_class, **opts)
|
87
|
-
serializer_class::SeregaConfig.include(ConfigInstanceMethods)
|
88
|
-
|
89
|
-
batch_loaders_class = Class.new(SeregaBatchLoaders)
|
90
|
-
batch_loaders_class.serializer_class = serializer_class
|
91
|
-
serializer_class.const_set(:SeregaBatchLoaders, batch_loaders_class)
|
92
|
-
|
93
|
-
batch_loader_class = Class.new(SeregaBatchLoader)
|
94
|
-
batch_loader_class.serializer_class = serializer_class
|
95
|
-
serializer_class.const_set(:SeregaBatchLoader, batch_loader_class)
|
96
|
-
|
97
|
-
if serializer_class.plugin_used?(:activerecord_preloads)
|
98
|
-
require_relative "lib/plugins_extensions/activerecord_preloads"
|
99
|
-
serializer_class::SeregaBatchLoader.include(PluginsExtensions::ActiveRecordPreloads::BatchLoaderInstanceMethods)
|
100
|
-
end
|
101
|
-
|
102
|
-
if serializer_class.plugin_used?(:formatters)
|
103
|
-
require_relative "lib/plugins_extensions/formatters"
|
104
|
-
serializer_class::SeregaBatchLoader.include(PluginsExtensions::Formatters::BatchLoaderInstanceMethods)
|
105
|
-
serializer_class::SeregaAttribute.include(PluginsExtensions::Formatters::SeregaAttributeInstanceMethods)
|
106
|
-
end
|
107
|
-
|
108
|
-
if serializer_class.plugin_used?(:if)
|
109
|
-
require_relative "lib/plugins_extensions/if"
|
110
|
-
serializer_class::SeregaObjectSerializer.include(PluginsExtensions::If::ObjectSerializerInstanceMethods123)
|
111
|
-
end
|
112
|
-
|
113
|
-
if serializer_class.plugin_used?(:preloads)
|
114
|
-
require_relative "lib/plugins_extensions/preloads"
|
115
|
-
serializer_class::SeregaAttributeNormalizer.include(PluginsExtensions::Preloads::AttributeNormalizerInstanceMethods)
|
116
|
-
end
|
117
|
-
|
118
|
-
config = serializer_class.config
|
119
|
-
config.attribute_keys << :batch
|
120
|
-
config.opts[:batch] = {loaders: {}, id_method: nil, auto_hide: false}
|
121
|
-
config.batch.auto_hide = opts[:auto_hide] if opts.key?(:auto_hide)
|
122
|
-
config.batch.id_method = opts[:id_method] if opts.key?(:id_method)
|
123
|
-
end
|
124
|
-
|
125
|
-
#
|
126
|
-
# Serega class additional/patched class methods
|
127
|
-
#
|
128
|
-
# @see Serega::SeregaConfig
|
129
|
-
#
|
130
|
-
module ClassMethods
|
131
|
-
private
|
132
|
-
|
133
|
-
def inherited(subclass)
|
134
|
-
super
|
135
|
-
|
136
|
-
batch_loaders_class = Class.new(self::SeregaBatchLoaders)
|
137
|
-
batch_loaders_class.serializer_class = subclass
|
138
|
-
subclass.const_set(:SeregaBatchLoaders, batch_loaders_class)
|
139
|
-
|
140
|
-
batch_loader_class = Class.new(self::SeregaBatchLoader)
|
141
|
-
batch_loader_class.serializer_class = subclass
|
142
|
-
subclass.const_set(:SeregaBatchLoader, batch_loader_class)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
#
|
147
|
-
# Serega additional/patched instance methods
|
148
|
-
#
|
149
|
-
# @see Serega::InstanceMethods
|
150
|
-
#
|
151
|
-
module InstanceMethods
|
152
|
-
private
|
153
|
-
|
154
|
-
#
|
155
|
-
# Loads batch loaded attributes after serialization
|
156
|
-
#
|
157
|
-
def serialize(object, opts)
|
158
|
-
batch_loaders = opts[:batch_loaders] = self.class::SeregaBatchLoaders.new
|
159
|
-
result = super
|
160
|
-
batch_loaders.load_all
|
161
|
-
result
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
register_plugin(Batch.plugin_name, Batch)
|
167
|
-
end
|
168
|
-
end
|
@@ -1,77 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Serega
|
4
|
-
module SeregaPlugins
|
5
|
-
module Batch
|
6
|
-
#
|
7
|
-
# Batch plugin config
|
8
|
-
#
|
9
|
-
class BatchConfig
|
10
|
-
attr_reader :opts
|
11
|
-
|
12
|
-
def initialize(opts)
|
13
|
-
@opts = opts
|
14
|
-
end
|
15
|
-
|
16
|
-
#
|
17
|
-
# Defines batch loader
|
18
|
-
#
|
19
|
-
# @param loader_name [Symbol] Batch loader name, that is used when defining attribute with batch loader.
|
20
|
-
# @param block [Proc] Block that can accept 3 parameters - ids, context, plan_point
|
21
|
-
# and returns hash with ids as keys and values are batch loaded objects
|
22
|
-
#
|
23
|
-
# @return [void]
|
24
|
-
#
|
25
|
-
def define(loader_name, callable = nil, &block)
|
26
|
-
if (!callable && !block) || (callable && block)
|
27
|
-
raise SeregaError, "Batch loader can be specified with one of arguments - callable value or &block"
|
28
|
-
end
|
29
|
-
|
30
|
-
callable ||= block
|
31
|
-
SeregaValidations::Utils::CheckExtraKeywordArg.call(callable, "batch loader `#{loader_name}`")
|
32
|
-
params_count = SeregaUtils::ParamsCount.call(callable, max_count: 3)
|
33
|
-
|
34
|
-
if params_count > 3
|
35
|
-
raise SeregaError, "Batch loader can have maximum 3 parameters (ids, context, plan)"
|
36
|
-
end
|
37
|
-
|
38
|
-
loaders[loader_name] = callable
|
39
|
-
end
|
40
|
-
|
41
|
-
# Shows defined loaders
|
42
|
-
# @return [Hash] defined loaders
|
43
|
-
def loaders
|
44
|
-
opts[:loaders]
|
45
|
-
end
|
46
|
-
|
47
|
-
# Shows option to auto hide attributes with :batch specified
|
48
|
-
# @return [Boolean, nil] option value
|
49
|
-
def auto_hide
|
50
|
-
opts[:auto_hide]
|
51
|
-
end
|
52
|
-
|
53
|
-
# @param value [Boolean] New :auto_hide option value
|
54
|
-
# @return [Boolean] New option value
|
55
|
-
def auto_hide=(value)
|
56
|
-
raise SeregaError, "Must have boolean value, #{value.inspect} provided" if (value != true) && (value != false)
|
57
|
-
opts[:auto_hide] = value
|
58
|
-
end
|
59
|
-
|
60
|
-
# Shows method name or callable object needed to get object identifier for batch load
|
61
|
-
# @return [Symbol, #call, nil] Default method name or callable object to get identifier
|
62
|
-
def id_method
|
63
|
-
opts[:id_method]
|
64
|
-
end
|
65
|
-
|
66
|
-
# Sets new identifier method name or callable value needed for batch loading
|
67
|
-
#
|
68
|
-
# @param value [Symbol, #call] New :id_method value
|
69
|
-
# @return [Boolean] New option value
|
70
|
-
def id_method=(value)
|
71
|
-
CheckBatchOptIdMethod.call(value)
|
72
|
-
opts[:id_method] = value
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
@@ -1,113 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Serega
|
4
|
-
module SeregaPlugins
|
5
|
-
module Batch
|
6
|
-
#
|
7
|
-
# Encapsulates point and according object_serializer
|
8
|
-
# so we can put batch loaded values to this serializer response
|
9
|
-
#
|
10
|
-
class SeregaBatchLoader
|
11
|
-
#
|
12
|
-
# Batch Loader instance methods
|
13
|
-
#
|
14
|
-
module InstanceMethods
|
15
|
-
# @return [Serega::SeregaPlanPoint]
|
16
|
-
attr_reader :point
|
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::SeregaPlanPoint]
|
26
|
-
#
|
27
|
-
# @return [Serega::SeregaPlugins::Batch::SeregaBatchLoader]
|
28
|
-
#
|
29
|
-
def initialize(object_serializer, point)
|
30
|
-
@object_serializer = object_serializer
|
31
|
-
@point = point
|
32
|
-
end
|
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
|
-
#
|
42
|
-
def remember(key, container)
|
43
|
-
(keys[key] ||= []) << container
|
44
|
-
end
|
45
|
-
|
46
|
-
#
|
47
|
-
# Loads this batch and assigns values to remembered containers
|
48
|
-
#
|
49
|
-
# @return [void]
|
50
|
-
#
|
51
|
-
def load
|
52
|
-
keys_values = keys_values()
|
53
|
-
|
54
|
-
each_key do |key, container|
|
55
|
-
value = keys_values.fetch(key) { point.batch[:default] }
|
56
|
-
final_value = object_serializer.__send__(:final_value, value, point)
|
57
|
-
object_serializer.__send__(:attach_final_value, final_value, point, container)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
private
|
62
|
-
|
63
|
-
def keys
|
64
|
-
@keys ||= {}
|
65
|
-
end
|
66
|
-
|
67
|
-
def each_key
|
68
|
-
keys.each do |key, containers|
|
69
|
-
containers.each do |container|
|
70
|
-
yield(key, container)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
# Patched in:
|
76
|
-
# - plugin batch (extension :activerecord_preloads - preloads data to found values)
|
77
|
-
# - plugin batch (extension :formatters - formats values)
|
78
|
-
def keys_values
|
79
|
-
ids = keys.keys
|
80
|
-
|
81
|
-
keys_values = load_keys_values(ids)
|
82
|
-
validate(keys_values)
|
83
|
-
|
84
|
-
keys_values
|
85
|
-
end
|
86
|
-
|
87
|
-
def load_keys_values(ids)
|
88
|
-
point.batch[:loader].call(ids, object_serializer.context, point)
|
89
|
-
rescue => error
|
90
|
-
raise reraise_with_serialized_attribute_details(error, point)
|
91
|
-
end
|
92
|
-
|
93
|
-
def validate(keys_values)
|
94
|
-
return if keys_values.is_a?(Hash)
|
95
|
-
|
96
|
-
attribute_name = "#{point.class.serializer_class}.#{point.name}"
|
97
|
-
raise SeregaError, "Batch loader for `#{attribute_name}` must return Hash, but #{keys_values.inspect} was returned"
|
98
|
-
end
|
99
|
-
|
100
|
-
def reraise_with_serialized_attribute_details(error, point)
|
101
|
-
raise error.exception(<<~MESSAGE.strip)
|
102
|
-
#{error.message}
|
103
|
-
(when serializing '#{point.name}' attribute in #{self.class.serializer_class})
|
104
|
-
MESSAGE
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
include InstanceMethods
|
109
|
-
extend Serega::SeregaHelpers::SerializerClassHelper
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Serega
|
4
|
-
module SeregaPlugins
|
5
|
-
module Batch
|
6
|
-
# Lists batch loaders registered during serialization
|
7
|
-
class SeregaBatchLoaders
|
8
|
-
# BatchLoaders instance methods
|
9
|
-
module InstanceMethods
|
10
|
-
#
|
11
|
-
# Initializes or fetches already initialized batch loader
|
12
|
-
#
|
13
|
-
# @param plan_point [Serega::SeregaPlanPoint] current plan point
|
14
|
-
# @param object_serializer[Serega::SeregaObjectSerializer] current object serializer
|
15
|
-
#
|
16
|
-
# @return [Serega::SeregaPlugins::Batch::SeregaBatchLoader] Batch Loader
|
17
|
-
#
|
18
|
-
def get(plan_point, object_serializer)
|
19
|
-
batch_loaders[plan_point] ||= self.class.serializer_class::SeregaBatchLoader.new(object_serializer, plan_point)
|
20
|
-
end
|
21
|
-
|
22
|
-
#
|
23
|
-
# Loads all registered batches and removes them from registered list
|
24
|
-
#
|
25
|
-
def load_all
|
26
|
-
return unless defined?(@batch_loaders)
|
27
|
-
|
28
|
-
while (_point, batch_loader = batch_loaders.shift)
|
29
|
-
batch_loader.load
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def batch_loaders
|
36
|
-
@batch_loaders ||= {}.compare_by_identity
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
include InstanceMethods
|
41
|
-
extend Serega::SeregaHelpers::SerializerClassHelper
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Serega
|
4
|
-
module SeregaPlugins
|
5
|
-
module Batch
|
6
|
-
#
|
7
|
-
# Serega::SeregaAttribute additional/patched class methods
|
8
|
-
#
|
9
|
-
# @see Serega::SeregaAttribute
|
10
|
-
#
|
11
|
-
module AttributeInstanceMethods
|
12
|
-
#
|
13
|
-
# @return [nil, Hash] :batch option
|
14
|
-
#
|
15
|
-
attr_reader :batch
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def set_normalized_vars(normalizer)
|
20
|
-
super
|
21
|
-
@batch = normalizer.batch
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,78 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Serega
|
4
|
-
module SeregaPlugins
|
5
|
-
module Batch
|
6
|
-
#
|
7
|
-
# SeregaAttributeNormalizer additional/patched instance methods
|
8
|
-
#
|
9
|
-
# @see SeregaAttributeNormalizer::AttributeInstanceMethods
|
10
|
-
#
|
11
|
-
module AttributeNormalizerInstanceMethods
|
12
|
-
#
|
13
|
-
# Returns normalized attribute :batch option with prepared :key and
|
14
|
-
# :default options. Option :loader will be prepared at serialization
|
15
|
-
# time as loaders are usually defined after attributes.
|
16
|
-
#
|
17
|
-
# @return [Hash] attribute :batch normalized options
|
18
|
-
#
|
19
|
-
def batch
|
20
|
-
return @batch if instance_variable_defined?(:@batch)
|
21
|
-
|
22
|
-
@batch = prepare_batch
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
#
|
28
|
-
# Patch for original `prepare_hide` method
|
29
|
-
#
|
30
|
-
# Marks attribute hidden if auto_hide option was set and attribute has batch loader
|
31
|
-
#
|
32
|
-
def prepare_hide
|
33
|
-
res = super
|
34
|
-
return res unless res.nil?
|
35
|
-
|
36
|
-
if batch
|
37
|
-
self.class.serializer_class.config.batch.auto_hide || nil
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def prepare_batch
|
42
|
-
batch = init_opts[:batch]
|
43
|
-
return unless batch
|
44
|
-
|
45
|
-
loader = prepare_batch_loader(batch[:loader])
|
46
|
-
|
47
|
-
id_method = batch[:id_method] || self.class.serializer_class.config.batch.id_method
|
48
|
-
id_method = prepare_batch_id_method(id_method)
|
49
|
-
|
50
|
-
{loader: loader, id_method: id_method, default: default}
|
51
|
-
end
|
52
|
-
|
53
|
-
def prepare_batch_id_method(id_method)
|
54
|
-
return proc { |object| object.public_send(id_method) } if id_method.is_a?(Symbol)
|
55
|
-
|
56
|
-
params_count = SeregaUtils::ParamsCount.call(id_method, max_count: 2)
|
57
|
-
case params_count
|
58
|
-
when 0 then proc { id_method.call }
|
59
|
-
when 1 then proc { |object| id_method.call(object) }
|
60
|
-
else id_method
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def prepare_batch_loader(loader)
|
65
|
-
loader = self.class.serializer_class.config.batch.loaders.fetch(loader) if loader.is_a?(Symbol)
|
66
|
-
|
67
|
-
params_count = SeregaUtils::ParamsCount.call(loader, max_count: 3)
|
68
|
-
case params_count
|
69
|
-
when 0 then proc { loader.call }
|
70
|
-
when 1 then proc { |object| loader.call(object) }
|
71
|
-
when 2 then proc { |object, context| loader.call(object, context) }
|
72
|
-
else loader
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Serega
|
4
|
-
module SeregaPlugins
|
5
|
-
module Batch
|
6
|
-
#
|
7
|
-
# Serega::SeregaValidations::CheckAttributeParams additional/patched class methods
|
8
|
-
#
|
9
|
-
# @see Serega::SeregaValidations::CheckAttributeParams
|
10
|
-
#
|
11
|
-
module CheckAttributeParamsInstanceMethods
|
12
|
-
private
|
13
|
-
|
14
|
-
def check_opts
|
15
|
-
super
|
16
|
-
|
17
|
-
CheckOptBatch.call(opts, block, self.class.serializer_class)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Serega
|
4
|
-
module SeregaPlugins
|
5
|
-
module Batch
|
6
|
-
#
|
7
|
-
# Config class additional/patched instance methods
|
8
|
-
#
|
9
|
-
# @see Serega::SeregaConfig
|
10
|
-
#
|
11
|
-
module ConfigInstanceMethods
|
12
|
-
#
|
13
|
-
# Returns all batch loaders registered for current serializer
|
14
|
-
#
|
15
|
-
# @return [Serega::SeregaPlugins::Batch::BatchConfig] configuration for batch loaded attributes
|
16
|
-
#
|
17
|
-
def batch
|
18
|
-
@batch ||= BatchConfig.new(opts.fetch(:batch))
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Serega
|
4
|
-
module SeregaPlugins
|
5
|
-
module Batch
|
6
|
-
#
|
7
|
-
# SeregaObjectSerializer additional/patched class methods
|
8
|
-
#
|
9
|
-
# @see Serega::SeregaObjectSerializer
|
10
|
-
#
|
11
|
-
module SeregaObjectSerializerInstanceMethods
|
12
|
-
private
|
13
|
-
|
14
|
-
def attach_value(object, point, container)
|
15
|
-
batch = point.batch
|
16
|
-
return super unless batch
|
17
|
-
|
18
|
-
remember_key_for_batch_loading(batch, object, point, container)
|
19
|
-
end
|
20
|
-
|
21
|
-
def remember_key_for_batch_loading(batch, object, point, container)
|
22
|
-
id = batch[:id_method].call(object, context)
|
23
|
-
batch_loader(point).remember(id, container)
|
24
|
-
container[point.name] = nil # Reserve attribute place in resulted hash. We will set correct value later
|
25
|
-
end
|
26
|
-
|
27
|
-
def batch_loader(point)
|
28
|
-
batch_loaders = opts[:batch_loaders]
|
29
|
-
raise_batch_plugin_for_serializer_not_defined(point) unless batch_loaders
|
30
|
-
batch_loaders.get(point, self)
|
31
|
-
end
|
32
|
-
|
33
|
-
def raise_batch_plugin_for_serializer_not_defined(point)
|
34
|
-
root_plan = point.plan
|
35
|
-
root_plan = plan.parent_plan_point.plan while root_plan.parent_plan_point
|
36
|
-
current_serializer = root_plan.serializer_class
|
37
|
-
nested_serializer = self.class.serializer_class
|
38
|
-
|
39
|
-
raise SeregaError,
|
40
|
-
"Plugin :batch must be added to current serializer (#{current_serializer})" \
|
41
|
-
" to load attributes with :batch option in nested serializer (#{nested_serializer})"
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Serega
|
4
|
-
module SeregaPlugins
|
5
|
-
module Batch
|
6
|
-
#
|
7
|
-
# Serega::SeregaPlanPoint additional/patched class methods
|
8
|
-
#
|
9
|
-
# @see SeregaAttribute
|
10
|
-
#
|
11
|
-
module PlanPointInstanceMethods
|
12
|
-
#
|
13
|
-
# Returns attribute :batch option with prepared loader
|
14
|
-
# @return [Hash] attribute :batch option
|
15
|
-
#
|
16
|
-
def batch
|
17
|
-
attribute.batch
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Serega
|
4
|
-
module SeregaPlugins
|
5
|
-
module Batch
|
6
|
-
#
|
7
|
-
# Extensions (mini-plugins) that are enabled when :batch plugin used with other plugins
|
8
|
-
#
|
9
|
-
module PluginsExtensions
|
10
|
-
#
|
11
|
-
# Extension that is used when :batch plugin used with :active_record_preloads plugin
|
12
|
-
#
|
13
|
-
module ActiveRecordPreloads
|
14
|
-
#
|
15
|
-
# BatchLoader additional/patched instance methods
|
16
|
-
#
|
17
|
-
# @see Serega::SeregaPlugins::Batch::SeregaBatchLoader
|
18
|
-
#
|
19
|
-
module BatchLoaderInstanceMethods
|
20
|
-
private
|
21
|
-
|
22
|
-
# Preloads required associations to batch-loaded records
|
23
|
-
def keys_values
|
24
|
-
data = super
|
25
|
-
|
26
|
-
if point.child_plan
|
27
|
-
associations = point.preloads
|
28
|
-
return data if associations.empty?
|
29
|
-
|
30
|
-
records = data.values
|
31
|
-
records.flatten!(1)
|
32
|
-
|
33
|
-
ActiverecordPreloads::Preloader.preload(records, associations)
|
34
|
-
end
|
35
|
-
|
36
|
-
data
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|