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.
- checksums.yaml +4 -4
- data/README.md +62 -13
- data/VERSION +1 -1
- data/lib/serega/attribute.rb +9 -4
- data/lib/serega/attribute_normalizer.rb +4 -13
- data/lib/serega/object_serializer.rb +11 -0
- data/lib/serega/plan.rb +20 -25
- data/lib/serega/plan_point.rb +13 -16
- data/lib/serega/plugins/batch/batch.rb +7 -245
- data/lib/serega/plugins/batch/lib/batch_config.rb +82 -0
- data/lib/serega/plugins/batch/lib/loader.rb +25 -7
- data/lib/serega/plugins/batch/lib/modules/attribute.rb +26 -0
- data/lib/serega/plugins/batch/lib/modules/attribute_normalizer.rb +65 -0
- data/lib/serega/plugins/batch/lib/modules/check_attribute_params.rb +22 -0
- data/lib/serega/plugins/batch/lib/modules/config.rb +23 -0
- data/lib/serega/plugins/batch/lib/modules/object_serializer.rb +46 -0
- data/lib/serega/plugins/batch/lib/modules/plan_point.rb +39 -0
- data/lib/serega/plugins/metadata/metadata.rb +5 -0
- data/lib/serega/plugins/preloads/lib/modules/attribute.rb +28 -0
- data/lib/serega/plugins/preloads/lib/modules/attribute_normalizer.rb +99 -0
- data/lib/serega/plugins/preloads/lib/modules/check_attribute_params.rb +22 -0
- data/lib/serega/plugins/preloads/lib/modules/config.rb +19 -0
- data/lib/serega/plugins/preloads/lib/modules/plan_point.rb +41 -0
- data/lib/serega/plugins/preloads/lib/preload_paths.rb +46 -0
- data/lib/serega/plugins/preloads/lib/preloads_config.rb +62 -0
- data/lib/serega/plugins/preloads/lib/preloads_constructor.rb +20 -7
- data/lib/serega/plugins/preloads/preloads.rb +12 -210
- data/lib/serega/plugins/preloads/validations/check_opt_preload_path.rb +54 -15
- metadata +16 -3
- data/lib/serega/plugins/preloads/lib/main_preload_path.rb +0 -53
@@ -0,0 +1,82 @@
|
|
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 - keys, context, plan_point
|
21
|
+
# and returns hash where ids are keys and values are batch loaded objects/
|
22
|
+
#
|
23
|
+
# @return [void]
|
24
|
+
#
|
25
|
+
def define(loader_name, &block)
|
26
|
+
unless block
|
27
|
+
raise SeregaError, "Block must be given to #define method"
|
28
|
+
end
|
29
|
+
|
30
|
+
params = block.parameters
|
31
|
+
if params.count > 3 || !params.all? { |param| (param[0] == :req) || (param[0] == :opt) }
|
32
|
+
raise SeregaError, "Block can have maximum 3 regular parameters"
|
33
|
+
end
|
34
|
+
|
35
|
+
loaders[loader_name] = block
|
36
|
+
end
|
37
|
+
|
38
|
+
# Shows defined loaders
|
39
|
+
# @return [Hash] defined loaders
|
40
|
+
def loaders
|
41
|
+
opts[:loaders]
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Finds previously defined batch loader by name
|
46
|
+
#
|
47
|
+
# @param loader_name [Symbol]
|
48
|
+
#
|
49
|
+
# @return [Proc] batch loader block
|
50
|
+
def fetch_loader(loader_name)
|
51
|
+
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| ... }")
|
52
|
+
end
|
53
|
+
|
54
|
+
# Shows option to auto hide attributes with :batch specified
|
55
|
+
# @return [Boolean, nil] option value
|
56
|
+
def auto_hide
|
57
|
+
opts[:auto_hide]
|
58
|
+
end
|
59
|
+
|
60
|
+
# @param value [Boolean] New :auto_hide option value
|
61
|
+
# @return [Boolean] New option value
|
62
|
+
def auto_hide=(value)
|
63
|
+
raise SeregaError, "Must have boolean value, #{value.inspect} provided" if (value != true) && (value != false)
|
64
|
+
opts[:auto_hide] = value
|
65
|
+
end
|
66
|
+
|
67
|
+
# Shows default key for :batch option
|
68
|
+
# @return [Symbol, nil] default key for :batch option
|
69
|
+
def default_key
|
70
|
+
opts[:default_key]
|
71
|
+
end
|
72
|
+
|
73
|
+
# @param value [Symbol] New :default_key option value
|
74
|
+
# @return [Boolean] New option value
|
75
|
+
def default_key=(value)
|
76
|
+
raise SeregaError, "Must be a Symbol, #{value.inspect} provided" unless value.is_a?(Symbol)
|
77
|
+
opts[:default_key] = value
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -60,6 +60,10 @@ class Serega
|
|
60
60
|
|
61
61
|
private
|
62
62
|
|
63
|
+
def keys
|
64
|
+
@keys ||= {}
|
65
|
+
end
|
66
|
+
|
63
67
|
def each_key
|
64
68
|
keys.each do |key, containers|
|
65
69
|
containers.each do |container|
|
@@ -74,16 +78,30 @@ class Serega
|
|
74
78
|
def keys_values
|
75
79
|
ids = keys.keys
|
76
80
|
|
77
|
-
|
78
|
-
|
81
|
+
keys_values = load_keys_values(ids)
|
82
|
+
validate(keys_values)
|
79
83
|
|
80
|
-
|
81
|
-
raise SeregaError, "Batch loader for `#{attribute_name}` must return Hash, but #{vals.inspect} was returned"
|
82
|
-
end
|
84
|
+
keys_values
|
83
85
|
end
|
84
86
|
|
85
|
-
def
|
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
|
87
105
|
end
|
88
106
|
end
|
89
107
|
|
@@ -0,0 +1,26 @@
|
|
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
|
@@ -0,0 +1,65 @@
|
|
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
|
+
# take loader
|
46
|
+
loader = batch[:loader]
|
47
|
+
|
48
|
+
# take key
|
49
|
+
key = batch[:key] || self.class.serializer_class.config.batch.default_key
|
50
|
+
proc_key =
|
51
|
+
if key.is_a?(Symbol)
|
52
|
+
proc { |object| object.public_send(key) }
|
53
|
+
else
|
54
|
+
key
|
55
|
+
end
|
56
|
+
|
57
|
+
# take default value
|
58
|
+
default = batch.fetch(:default) { many ? FROZEN_EMPTY_ARRAY : nil }
|
59
|
+
|
60
|
+
{loader: loader, key: proc_key, default: default}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,22 @@
|
|
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
|
@@ -0,0 +1,23 @@
|
|
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
|
@@ -0,0 +1,46 @@
|
|
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
|
+
key = batch[:key].call(object, context)
|
23
|
+
batch_loader(point).remember(key, 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
|
@@ -0,0 +1,39 @@
|
|
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
|
+
attr_reader :batch
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def set_normalized_vars
|
21
|
+
super
|
22
|
+
@batch = prepare_batch
|
23
|
+
end
|
24
|
+
|
25
|
+
def prepare_batch
|
26
|
+
batch = attribute.batch
|
27
|
+
if batch
|
28
|
+
loader = batch[:loader]
|
29
|
+
if loader.is_a?(Symbol)
|
30
|
+
batch_config = attribute.class.serializer_class.config.batch
|
31
|
+
batch[:loader] = batch_config.fetch_loader(loader)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
batch
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -194,6 +194,11 @@ class Serega
|
|
194
194
|
next unless metadata
|
195
195
|
|
196
196
|
deep_merge_metadata(hash, metadata)
|
197
|
+
rescue => error
|
198
|
+
raise error.exception(<<~MESSAGE.strip)
|
199
|
+
#{error.message}
|
200
|
+
(when serializing meta_attribute #{meta_attribute.path.inspect} in #{self.class})
|
201
|
+
MESSAGE
|
197
202
|
end
|
198
203
|
end
|
199
204
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module SeregaPlugins
|
5
|
+
module Preloads
|
6
|
+
#
|
7
|
+
# Serega::SeregaAttribute additional/patched instance methods
|
8
|
+
#
|
9
|
+
# @see Serega::SeregaAttribute::AttributeInstanceMethods
|
10
|
+
#
|
11
|
+
module AttributeInstanceMethods
|
12
|
+
# @return [Hash, nil] normalized preloads of current attribute
|
13
|
+
attr_reader :preloads
|
14
|
+
|
15
|
+
# @return [Array] normalized preloads_path of current attribute
|
16
|
+
attr_reader :preloads_path
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def set_normalized_vars(normalizer)
|
21
|
+
super
|
22
|
+
@preloads = normalizer.preloads
|
23
|
+
@preloads_path = normalizer.preloads_path
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module SeregaPlugins
|
5
|
+
module Preloads
|
6
|
+
#
|
7
|
+
# Serega::SeregaAttributeNormalizer additional/patched instance methods
|
8
|
+
#
|
9
|
+
# @see SeregaAttributeNormalizer::AttributeNormalizerInstanceMethods
|
10
|
+
#
|
11
|
+
module AttributeNormalizerInstanceMethods
|
12
|
+
# @return [Hash,nil] normalized attribute preloads
|
13
|
+
def preloads
|
14
|
+
return @preloads if instance_variable_defined?(:@preloads)
|
15
|
+
|
16
|
+
@preloads = prepare_preloads
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Array, nil] normalized attribute preloads path
|
20
|
+
def preloads_path
|
21
|
+
return @preloads_path if instance_variable_defined?(:@preloads_path)
|
22
|
+
|
23
|
+
@preloads_path = prepare_preloads_path
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
#
|
29
|
+
# Patched in:
|
30
|
+
# - plugin :batch (extension :preloads - skips auto preloads when batch option provided)
|
31
|
+
#
|
32
|
+
def prepare_preloads
|
33
|
+
opts = init_opts
|
34
|
+
preloads_provided = opts.key?(:preload)
|
35
|
+
preloads =
|
36
|
+
if preloads_provided
|
37
|
+
opts[:preload]
|
38
|
+
elsif opts.key?(:serializer) && self.class.serializer_class.config.preloads.auto_preload_attributes_with_serializer
|
39
|
+
key
|
40
|
+
elsif opts.key?(:delegate) && self.class.serializer_class.config.preloads.auto_preload_attributes_with_delegate
|
41
|
+
opts[:delegate].fetch(:to)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Nil and empty hash differs as we can preload nested results to
|
45
|
+
# empty hash, but we will skip nested preloading if nil or false provided
|
46
|
+
return if preloads_provided && !preloads
|
47
|
+
|
48
|
+
FormatUserPreloads.call(preloads)
|
49
|
+
end
|
50
|
+
|
51
|
+
def prepare_preloads_path
|
52
|
+
path = init_opts.fetch(:preload_path) { default_preload_path(preloads) }
|
53
|
+
|
54
|
+
if path && path[0].is_a?(Array)
|
55
|
+
prepare_many_preload_paths(path)
|
56
|
+
else
|
57
|
+
prepare_one_preload_path(path)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def prepare_one_preload_path(path)
|
62
|
+
return unless path
|
63
|
+
|
64
|
+
case path
|
65
|
+
when Array
|
66
|
+
path.map(&:to_sym).freeze
|
67
|
+
else
|
68
|
+
[path.to_sym].freeze
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def prepare_many_preload_paths(paths)
|
73
|
+
paths.map { |path| prepare_one_preload_path(path) }.freeze
|
74
|
+
end
|
75
|
+
|
76
|
+
def default_preload_path(preloads)
|
77
|
+
return FROZEN_EMPTY_ARRAY if !preloads || preloads.empty?
|
78
|
+
|
79
|
+
[preloads.keys.first]
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# Patch for original `prepare_hide` method
|
84
|
+
# @see
|
85
|
+
#
|
86
|
+
# Marks attribute hidden if auto_hide_attribute_with_preloads option was set and attribute has preloads
|
87
|
+
#
|
88
|
+
def prepare_hide
|
89
|
+
res = super
|
90
|
+
return res unless res.nil?
|
91
|
+
|
92
|
+
if preloads && !preloads.empty?
|
93
|
+
self.class.serializer_class.config.preloads.auto_hide_attributes_with_preload || nil
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module SeregaPlugins
|
5
|
+
module Preloads
|
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
|
+
CheckOptPreload.call(opts)
|
17
|
+
CheckOptPreloadPath.call(opts)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module SeregaPlugins
|
5
|
+
module Preloads
|
6
|
+
#
|
7
|
+
# Config class additional/patched instance methods
|
8
|
+
#
|
9
|
+
# @see Serega::SeregaConfig
|
10
|
+
#
|
11
|
+
module ConfigInstanceMethods
|
12
|
+
# @return [Serega::SeregaPlugins::Preloads::PreloadsConfig] `preloads` plugin config
|
13
|
+
def preloads
|
14
|
+
@preloads ||= PreloadsConfig.new(opts.fetch(:preloads))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module SeregaPlugins
|
5
|
+
module Preloads
|
6
|
+
#
|
7
|
+
# Serega::SeregaPlanPoint additional/patched instance methods
|
8
|
+
#
|
9
|
+
# @see Serega::SeregaPlanPoint::InstanceMethods
|
10
|
+
#
|
11
|
+
module PlanPointInstanceMethods
|
12
|
+
#
|
13
|
+
# @return [Hash] preloads for nested attributes
|
14
|
+
#
|
15
|
+
attr_reader :preloads
|
16
|
+
|
17
|
+
#
|
18
|
+
# @return [Array<Symbol>] preloads path for current attribute
|
19
|
+
#
|
20
|
+
attr_reader :preloads_path
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def set_normalized_vars
|
25
|
+
super
|
26
|
+
|
27
|
+
@preloads = prepare_preloads
|
28
|
+
@preloads_path = prepare_preloads_path
|
29
|
+
end
|
30
|
+
|
31
|
+
def prepare_preloads
|
32
|
+
PreloadsConstructor.call(child_plan)
|
33
|
+
end
|
34
|
+
|
35
|
+
def prepare_preloads_path
|
36
|
+
attribute.preloads_path
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module SeregaPlugins
|
5
|
+
module Preloads
|
6
|
+
#
|
7
|
+
# Utility that helps to transform preloads to array of paths
|
8
|
+
#
|
9
|
+
# Example:
|
10
|
+
#
|
11
|
+
# call({ a: { b: { c: {}, d: {} } }, e: {} })
|
12
|
+
#
|
13
|
+
# => [
|
14
|
+
# [:a],
|
15
|
+
# [:a, :b],
|
16
|
+
# [:a, :b, :c],
|
17
|
+
# [:a, :b, :d],
|
18
|
+
# [:e]
|
19
|
+
# ]
|
20
|
+
class PreloadPaths
|
21
|
+
class << self
|
22
|
+
#
|
23
|
+
# Transforms user provided preloads to array of paths
|
24
|
+
#
|
25
|
+
# @param value [Array,Hash,String,Symbol,nil,false] preloads
|
26
|
+
#
|
27
|
+
# @return [Hash] preloads transformed to hash
|
28
|
+
#
|
29
|
+
def call(preloads, path = [], result = [])
|
30
|
+
preloads = FormatUserPreloads.call(preloads)
|
31
|
+
|
32
|
+
preloads.each do |key, nested_preloads|
|
33
|
+
path << key
|
34
|
+
result << path.dup
|
35
|
+
|
36
|
+
call(nested_preloads, path, result)
|
37
|
+
path.pop
|
38
|
+
end
|
39
|
+
|
40
|
+
result
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module SeregaPlugins
|
5
|
+
module Preloads
|
6
|
+
#
|
7
|
+
# Config for `preloads` plugin
|
8
|
+
#
|
9
|
+
class PreloadsConfig
|
10
|
+
# @return [Hash] preloads plugin options
|
11
|
+
attr_reader :opts
|
12
|
+
|
13
|
+
#
|
14
|
+
# Initializes context_metadata config object
|
15
|
+
#
|
16
|
+
# @param opts [Hash] options
|
17
|
+
#
|
18
|
+
# @return [Serega::SeregaPlugins::Metadata::MetadataConfig]
|
19
|
+
#
|
20
|
+
def initialize(opts)
|
21
|
+
@opts = opts
|
22
|
+
end
|
23
|
+
|
24
|
+
# @!method auto_preload_attributes_with_delegate
|
25
|
+
# @return [Boolean, nil] option value
|
26
|
+
#
|
27
|
+
# @!method auto_preload_attributes_with_delegate=(value)
|
28
|
+
# @param value [Boolean] New option value
|
29
|
+
# @return [Boolean] New option value
|
30
|
+
#
|
31
|
+
# @!method auto_preload_attributes_with_serializer
|
32
|
+
# @return [Boolean, nil] option value
|
33
|
+
#
|
34
|
+
# @!method auto_preload_attributes_with_serializer=(value)
|
35
|
+
# @param value [Boolean] New option value
|
36
|
+
# @return [Boolean] New option value
|
37
|
+
#
|
38
|
+
# @!method auto_hide_attributes_with_preload
|
39
|
+
# @return [Boolean, nil] option value
|
40
|
+
#
|
41
|
+
# @!method auto_hide_attributes_with_preload=(value)
|
42
|
+
# @param value [Boolean] New option value
|
43
|
+
# @return [Boolean] New option value
|
44
|
+
#
|
45
|
+
%i[
|
46
|
+
auto_preload_attributes_with_delegate
|
47
|
+
auto_preload_attributes_with_serializer
|
48
|
+
auto_hide_attributes_with_preload
|
49
|
+
].each do |method_name|
|
50
|
+
define_method(method_name) do
|
51
|
+
opts.fetch(method_name)
|
52
|
+
end
|
53
|
+
|
54
|
+
define_method("#{method_name}=") do |value|
|
55
|
+
raise SeregaError, "Must have boolean value, #{value.inspect} provided" if (value != true) && (value != false)
|
56
|
+
opts[method_name] = value
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|