serega 0.42.0 → 0.50.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 +124 -1207
- data/VERSION +1 -1
- data/lib/serega/attribute.rb +186 -131
- data/lib/serega/attribute_normalizer.rb +164 -345
- data/lib/serega/attribute_normalizers/batch.rb +45 -0
- data/lib/serega/attribute_normalizers/block.rb +81 -0
- data/lib/serega/attribute_normalizers/delegate.rb +34 -0
- data/lib/serega/attribute_normalizers/hash_access.rb +37 -0
- data/lib/serega/attribute_normalizers/preloads.rb +46 -0
- data/lib/serega/attribute_value_resolvers/batch.rb +5 -54
- data/lib/serega/attribute_value_resolvers/const.rb +2 -24
- data/lib/serega/attribute_value_resolvers/delegate.rb +17 -28
- data/lib/serega/attribute_value_resolvers/hash_access.rb +34 -52
- data/lib/serega/attribute_value_resolvers/keyword.rb +10 -25
- data/lib/serega/attribute_values.rb +46 -0
- data/lib/serega/batch_loader.rb +37 -0
- data/lib/serega/conditions.rb +56 -0
- data/lib/serega/config.rb +105 -144
- data/lib/serega/engine/pulls.rb +64 -0
- data/lib/serega/engine/run.rb +106 -0
- data/lib/serega/errors.rb +36 -8
- data/lib/serega/formatter.rb +98 -0
- data/lib/serega/plan/cache.rb +96 -0
- data/lib/serega/plan/per_ractor_cache.rb +23 -0
- data/lib/serega/plan.rb +101 -128
- data/lib/serega/plan_point.rb +44 -151
- data/lib/serega/plugins/activerecord_preloads/activerecord_preloads.rb +13 -80
- data/lib/serega/plugins/activerecord_preloads/lib/preloader.rb +8 -75
- data/lib/serega/plugins/context_metadata/context_metadata.rb +40 -123
- data/lib/serega/plugins/metadata/check_params.rb +80 -0
- data/lib/serega/plugins/metadata/meta_attribute.rb +40 -79
- data/lib/serega/plugins/metadata/metadata.rb +40 -168
- data/lib/serega/plugins/root/root.rb +91 -235
- data/lib/serega/plugins.rb +16 -49
- data/lib/serega/presenter.rb +61 -19
- data/lib/serega/result_builder.rb +68 -0
- data/lib/serega/result_code.rb +203 -0
- data/lib/serega/shareable.rb +52 -0
- data/lib/serega/source_group.rb +187 -0
- data/lib/serega/utils/collection_detector.rb +19 -13
- data/lib/serega/utils/deep_merge.rb +26 -0
- data/lib/serega/utils/enum_deep_dup.rb +10 -16
- data/lib/serega/utils/enum_deep_freeze.rb +8 -14
- data/lib/serega/utils/method_signature.rb +6 -15
- data/lib/serega/utils/parse_string_modifiers.rb +63 -0
- data/lib/serega/utils/ractor_local.rb +36 -0
- data/lib/serega/utils/serialized_attribute_error.rb +60 -20
- data/lib/serega/utils/to_hash.rb +5 -26
- data/lib/serega/validations/attribute/check_block.rb +3 -15
- data/lib/serega/validations/attribute/check_name.rb +4 -15
- data/lib/serega/validations/attribute/check_opt_base_serializer.rb +3 -15
- data/lib/serega/validations/attribute/check_opt_batch.rb +26 -56
- data/lib/serega/validations/attribute/check_opt_condition.rb +55 -0
- data/lib/serega/validations/attribute/check_opt_delegate.rb +10 -63
- data/lib/serega/validations/attribute/check_opt_format.rb +36 -0
- data/lib/serega/validations/attribute/check_opt_hash_access.rb +11 -59
- data/lib/serega/validations/attribute/check_opt_hide.rb +3 -14
- data/lib/serega/validations/attribute/check_opt_many.rb +18 -20
- data/lib/serega/validations/attribute/check_opt_method.rb +3 -25
- data/lib/serega/validations/attribute/check_opt_preload.rb +3 -26
- data/lib/serega/validations/attribute/check_opt_serializer.rb +4 -18
- data/lib/serega/validations/attribute/check_opt_value.rb +3 -21
- data/lib/serega/validations/check_attribute_params.rb +92 -71
- data/lib/serega/validations/check_batch_loader_params.rb +43 -62
- data/lib/serega/validations/check_formatter.rb +80 -0
- data/lib/serega/validations/check_serialize_keywords.rb +23 -0
- data/lib/serega/validations/initiate/check_modifiers.rb +14 -20
- data/lib/serega/validations/utils/check_allowed_keys.rb +3 -13
- data/lib/serega/validations/utils/check_hash_access_value.rb +44 -0
- data/lib/serega/validations/utils/check_opt_is_bool.rb +3 -13
- data/lib/serega/validations/utils/check_opt_is_hash.rb +3 -13
- data/lib/serega/validations/utils/check_opt_is_string_or_symbol.rb +3 -13
- data/lib/serega/version.rb +1 -4
- data/lib/serega.rb +459 -388
- data/sig/serega/plugins.rbs +49 -0
- data/sig/serega.rbs +142 -0
- metadata +42 -38
- data/lib/serega/data_builder.rb +0 -54
- data/lib/serega/engine/level.rb +0 -59
- data/lib/serega/engine/level_queue.rb +0 -56
- data/lib/serega/engine/loader.rb +0 -70
- data/lib/serega/helpers/serializer_class_helper.rb +0 -19
- data/lib/serega/object_serializer.rb +0 -125
- data/lib/serega/plugins/camel_case/camel_case.rb +0 -213
- data/lib/serega/plugins/depth_limit/depth_limit.rb +0 -206
- data/lib/serega/plugins/explicit_many_option/explicit_many_option.rb +0 -69
- data/lib/serega/plugins/explicit_many_option/validations/check_opt_many.rb +0 -38
- data/lib/serega/plugins/formatters/formatters.rb +0 -322
- data/lib/serega/plugins/if/if.rb +0 -287
- data/lib/serega/plugins/if/validations/check_opt_if.rb +0 -72
- data/lib/serega/plugins/if/validations/check_opt_if_value.rb +0 -77
- data/lib/serega/plugins/if/validations/check_opt_unless.rb +0 -72
- data/lib/serega/plugins/if/validations/check_opt_unless_value.rb +0 -77
- data/lib/serega/plugins/metadata/validations/check_block.rb +0 -47
- data/lib/serega/plugins/metadata/validations/check_opt_const.rb +0 -39
- data/lib/serega/plugins/metadata/validations/check_opt_hide_empty.rb +0 -35
- data/lib/serega/plugins/metadata/validations/check_opt_hide_nil.rb +0 -35
- data/lib/serega/plugins/metadata/validations/check_opt_value.rb +0 -61
- data/lib/serega/plugins/metadata/validations/check_opts.rb +0 -59
- data/lib/serega/plugins/metadata/validations/check_path.rb +0 -50
- data/lib/serega/plugins/string_modifiers/parse_string_modifiers.rb +0 -111
- data/lib/serega/plugins/string_modifiers/string_modifiers.rb +0 -63
- data/lib/serega/utils/symbol_name.rb +0 -39
- data/lib/serega/validations/attribute/check_opt_const.rb +0 -40
- data/lib/serega/validations/check_initiate_params.rb +0 -57
- data/lib/serega/validations/check_serialize_params.rb +0 -54
|
@@ -1,31 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Serega
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
# @private
|
|
7
|
-
module Attribute
|
|
4
|
+
module SeregaValidations # :nodoc:
|
|
5
|
+
module Attribute # :nodoc:
|
|
8
6
|
#
|
|
9
7
|
# Attribute `name` parameter validator
|
|
10
8
|
#
|
|
11
|
-
#
|
|
12
|
-
class CheckName
|
|
9
|
+
class CheckName # :nodoc:
|
|
13
10
|
# Regexp for valid attribute name
|
|
14
11
|
FORMAT = /\A[\w~-]+\z/
|
|
15
12
|
|
|
16
13
|
class << self
|
|
17
|
-
#
|
|
18
14
|
# Checks allowed characters.
|
|
19
15
|
# Allowed characters: "a-z", "A-Z", "0-9", "_", "-", "~".
|
|
20
|
-
#
|
|
21
|
-
# @param name [String, Symbol] Attribute name
|
|
22
|
-
#
|
|
23
|
-
# @raise [SeregaError] when name has invalid format
|
|
24
|
-
# @return [void]
|
|
25
|
-
#
|
|
26
16
|
def call(name)
|
|
27
|
-
name
|
|
28
|
-
raise SeregaError, message(name) unless FORMAT.match?(name)
|
|
17
|
+
raise SeregaError, message(name.to_s) unless FORMAT.match?(name)
|
|
29
18
|
end
|
|
30
19
|
|
|
31
20
|
private
|
|
@@ -1,28 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Serega
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
# @private
|
|
7
|
-
module Attribute
|
|
4
|
+
module SeregaValidations # :nodoc:
|
|
5
|
+
module Attribute # :nodoc:
|
|
8
6
|
#
|
|
9
7
|
# Attribute `:base_serializer` option validator
|
|
10
8
|
#
|
|
11
|
-
#
|
|
12
|
-
class CheckOptBaseSerializer
|
|
9
|
+
class CheckOptBaseSerializer # :nodoc:
|
|
13
10
|
class << self
|
|
14
|
-
#
|
|
15
11
|
# Checks attribute :base_serializer option. It specifies the parent
|
|
16
12
|
# class for the nested serializer defined with the attribute block,
|
|
17
13
|
# so it makes sense only when a block is provided.
|
|
18
|
-
#
|
|
19
|
-
# @param opts [Hash] Attribute options
|
|
20
|
-
# @param block [nil, Proc] Attribute block (defines a nested serializer)
|
|
21
|
-
#
|
|
22
|
-
# @raise [SeregaError] SeregaError that option has invalid value
|
|
23
|
-
#
|
|
24
|
-
# @return [void]
|
|
25
|
-
#
|
|
26
14
|
def call(opts, block = nil)
|
|
27
15
|
return unless opts.key?(:base_serializer)
|
|
28
16
|
|
|
@@ -1,84 +1,58 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Serega
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
# @private
|
|
7
|
-
module Attribute
|
|
4
|
+
module SeregaValidations # :nodoc:
|
|
5
|
+
module Attribute # :nodoc:
|
|
8
6
|
#
|
|
9
7
|
# Attribute `:batch` option validator
|
|
10
8
|
#
|
|
11
|
-
#
|
|
12
|
-
class CheckOptBatch
|
|
9
|
+
class CheckOptBatch # :nodoc:
|
|
13
10
|
class << self
|
|
14
|
-
#
|
|
15
11
|
# Checks attribute :batch option
|
|
16
|
-
|
|
17
|
-
# @param opts [Hash] Attribute options
|
|
18
|
-
#
|
|
19
|
-
# @raise [SeregaError] Attribute validation error
|
|
20
|
-
#
|
|
21
|
-
# @return [void]
|
|
22
|
-
#
|
|
23
|
-
def call(serializer_class, opts)
|
|
12
|
+
def call(serializer_class, name, opts)
|
|
24
13
|
return unless opts.key?(:batch)
|
|
25
14
|
|
|
26
|
-
|
|
27
|
-
|
|
15
|
+
check_type(opts)
|
|
16
|
+
batch = AttributeNormalizers::Batch.new(opts[:batch], name)
|
|
17
|
+
check_loaders_exist(serializer_class, batch)
|
|
18
|
+
check_usage_with_other_params(opts, batch)
|
|
28
19
|
end
|
|
29
20
|
|
|
30
21
|
private
|
|
31
22
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return if
|
|
36
|
-
|
|
37
|
-
if batch_opts.is_a?(Symbol) || batch_opts.is_a?(String)
|
|
38
|
-
check_loader_exists?(serializer_class, batch_opts)
|
|
39
|
-
else
|
|
40
|
-
Utils::CheckOptIsHash.call(opts, :batch)
|
|
41
|
-
check_opt_batch_use(serializer_class, batch_opts)
|
|
42
|
-
check_opt_batch_id(batch_opts)
|
|
43
|
-
check_opt_batch_extra_opts(batch_opts)
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def check_opt_batch_use(serializer_class, batch_opts)
|
|
48
|
-
return unless batch_opts.key?(:use)
|
|
49
|
-
|
|
50
|
-
batch_loader_name = batch_opts[:use]
|
|
51
|
-
return if batch_loader_name.respond_to?(:call)
|
|
23
|
+
# `true`, a loader name, a callable or a Hash with :use and :id
|
|
24
|
+
def check_type(opts)
|
|
25
|
+
batch = opts[:batch]
|
|
26
|
+
return if batch == true || batch.is_a?(Symbol) || batch.is_a?(String) || batch.respond_to?(:call)
|
|
52
27
|
|
|
53
|
-
|
|
28
|
+
Utils::CheckOptIsHash.call(opts, :batch)
|
|
29
|
+
Utils::CheckAllowedKeys.call(batch, %i[use id], :batch)
|
|
30
|
+
check_id(batch)
|
|
54
31
|
end
|
|
55
32
|
|
|
56
|
-
def
|
|
57
|
-
return unless
|
|
33
|
+
def check_id(batch)
|
|
34
|
+
return unless batch.key?(:id)
|
|
58
35
|
|
|
59
|
-
id_method_name =
|
|
36
|
+
id_method_name = batch[:id]
|
|
60
37
|
return if id_method_name.is_a?(Symbol) || id_method_name.is_a?(String)
|
|
61
38
|
|
|
62
39
|
raise SeregaError, "Invalid batch option `:id` value, it can be a Symbol or a String"
|
|
63
40
|
end
|
|
64
41
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
42
|
+
# Checks the names as given, thus the error shows a String name as a String
|
|
43
|
+
def check_loaders_exist(serializer_class, batch)
|
|
44
|
+
return if batch.inline?
|
|
45
|
+
|
|
46
|
+
Array(batch.use).each do |batch_loader_name|
|
|
68
47
|
next if serializer_class.batch_loaders.key?(batch_loader_name.to_sym)
|
|
69
48
|
|
|
70
49
|
raise SeregaError, "Batch loader with name `#{batch_loader_name.inspect}` is not defined"
|
|
71
50
|
end
|
|
72
51
|
end
|
|
73
52
|
|
|
74
|
-
def
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
def check_usage_with_other_params(opts)
|
|
79
|
-
batch = opts[:batch]
|
|
80
|
-
use_id = batch.is_a?(Hash) && batch.key?(:id)
|
|
81
|
-
use_multiple = batch.is_a?(Hash) && (Array(batch[:use]).size > 1)
|
|
53
|
+
def check_usage_with_other_params(opts, batch)
|
|
54
|
+
use_id = !batch.id.nil?
|
|
55
|
+
use_multiple = Array(batch.use).size > 1
|
|
82
56
|
value_added = opts.key?(:value)
|
|
83
57
|
|
|
84
58
|
if use_multiple && use_id
|
|
@@ -92,10 +66,6 @@ class Serega
|
|
|
92
66
|
if use_id && value_added
|
|
93
67
|
raise SeregaError, "Option `batch.id` should not be used when :value option provided directly"
|
|
94
68
|
end
|
|
95
|
-
|
|
96
|
-
raise SeregaError, "Option :batch can not be used together with option :method" if opts.key?(:method)
|
|
97
|
-
raise SeregaError, "Option :batch can not be used together with option :const" if opts.key?(:const)
|
|
98
|
-
raise SeregaError, "Option :batch can not be used together with option :delegate" if opts.key?(:delegate)
|
|
99
69
|
end
|
|
100
70
|
end
|
|
101
71
|
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Serega
|
|
4
|
+
module SeregaValidations # :nodoc:
|
|
5
|
+
module Attribute # :nodoc:
|
|
6
|
+
#
|
|
7
|
+
# Validator for attribute :if, :unless, :if_value and :unless_value options
|
|
8
|
+
#
|
|
9
|
+
class CheckOptCondition # :nodoc:
|
|
10
|
+
# Options whose condition receives the serialized value, not the object
|
|
11
|
+
VALUE_OPTIONS = %i[if_value unless_value].freeze
|
|
12
|
+
|
|
13
|
+
# Signatures from MethodSignature: up to two positional parameters and
|
|
14
|
+
# the :ctx keyword
|
|
15
|
+
VALID_SIGNATURES = %w[0 1 2 1_ctx 2_ctx].freeze
|
|
16
|
+
|
|
17
|
+
class << self
|
|
18
|
+
# Checks the condition option `name`: a Symbol, a Proc or an object
|
|
19
|
+
# that responds to :call
|
|
20
|
+
def call(opts, name)
|
|
21
|
+
return unless opts.key?(name)
|
|
22
|
+
|
|
23
|
+
parameter = VALUE_OPTIONS.include?(name) ? "value" : "object"
|
|
24
|
+
check_type(opts[name], name, parameter)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def check_type(condition, name, parameter)
|
|
30
|
+
return if condition.is_a?(Symbol)
|
|
31
|
+
raise SeregaError, must_be_callable(name) unless condition.respond_to?(:call)
|
|
32
|
+
|
|
33
|
+
signature = SeregaUtils::MethodSignature.call(condition, pos_limit: 2, keyword_args: [:ctx])
|
|
34
|
+
raise SeregaError, signature_error(name, parameter) unless VALID_SIGNATURES.include?(signature)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def must_be_callable(name)
|
|
38
|
+
"Invalid attribute option #{name.inspect}. It must be a Symbol, a Proc or respond to :call"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def signature_error(name, parameter)
|
|
42
|
+
<<~ERROR.strip
|
|
43
|
+
Invalid attribute option #{name.inspect} parameters, valid parameters signatures:
|
|
44
|
+
- ()
|
|
45
|
+
- (#{parameter})
|
|
46
|
+
- (#{parameter}, context)
|
|
47
|
+
- (#{parameter}, :ctx)
|
|
48
|
+
- (#{parameter}, context, :ctx)
|
|
49
|
+
ERROR
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -1,47 +1,30 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Serega
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
# @private
|
|
7
|
-
module Attribute
|
|
4
|
+
module SeregaValidations # :nodoc:
|
|
5
|
+
module Attribute # :nodoc:
|
|
8
6
|
#
|
|
9
7
|
# Attribute `:delegate` option validator
|
|
10
8
|
#
|
|
11
|
-
#
|
|
12
|
-
class CheckOptDelegate
|
|
9
|
+
class CheckOptDelegate # :nodoc:
|
|
13
10
|
class << self
|
|
14
|
-
#
|
|
15
11
|
# Checks attribute :delegate option
|
|
16
12
|
# It must have :to option and can have :optional allow_nil option
|
|
17
|
-
#
|
|
18
|
-
# @param opts [Hash] Attribute options
|
|
19
|
-
#
|
|
20
|
-
# @raise [SeregaError] Attribute validation error
|
|
21
|
-
#
|
|
22
|
-
# @return [void]
|
|
23
|
-
#
|
|
24
13
|
def call(opts)
|
|
25
14
|
return unless opts.key?(:delegate)
|
|
26
15
|
|
|
27
|
-
check_opt_delegate(opts)
|
|
28
|
-
check_usage_with_other_params(opts)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
private
|
|
32
|
-
|
|
33
|
-
def check_opt_delegate(opts)
|
|
34
16
|
Utils::CheckOptIsHash.call(opts, :delegate)
|
|
35
17
|
|
|
36
18
|
delegate_opts = opts[:delegate]
|
|
37
19
|
check_opt_delegate_to(delegate_opts)
|
|
38
20
|
check_opt_delegate_method(delegate_opts)
|
|
39
21
|
check_opt_delegate_allow_nil(delegate_opts)
|
|
40
|
-
check_opt_delegate_to_hash_access(delegate_opts)
|
|
41
22
|
check_opt_delegate_hash_access(delegate_opts)
|
|
42
23
|
check_opt_delegate_extra_opts(delegate_opts)
|
|
43
24
|
end
|
|
44
25
|
|
|
26
|
+
private
|
|
27
|
+
|
|
45
28
|
def check_opt_delegate_to(delegate_opts)
|
|
46
29
|
to_exist = delegate_opts.key?(:to)
|
|
47
30
|
raise SeregaError, "Option :delegate must have a :to option" unless to_exist
|
|
@@ -59,53 +42,17 @@ class Serega
|
|
|
59
42
|
Utils::CheckOptIsBool.call(delegate_opts, :allow_nil)
|
|
60
43
|
end
|
|
61
44
|
|
|
62
|
-
# Hash access of the intermediate (:to) step
|
|
63
|
-
# forms
|
|
64
|
-
|
|
65
|
-
check_hash_access_value(delegate_opts, :to_hash_access)
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
# Hash access of the final (:method) step. Accepts the same forms
|
|
69
|
-
# as the attribute :hash_access option.
|
|
45
|
+
# Hash access of the intermediate (:to) step and of the final
|
|
46
|
+
# (:method) step. Both accept the forms of the attribute :hash_access
|
|
47
|
+
# option.
|
|
70
48
|
def check_opt_delegate_hash_access(delegate_opts)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def check_hash_access_value(delegate_opts, opt_name)
|
|
75
|
-
return unless delegate_opts.key?(opt_name)
|
|
76
|
-
|
|
77
|
-
value = delegate_opts[opt_name]
|
|
78
|
-
case value
|
|
79
|
-
when true, false then nil
|
|
80
|
-
when Symbol then check_hash_access_mode(value)
|
|
81
|
-
when Hash
|
|
82
|
-
Utils::CheckAllowedKeys.call(value, %i[mode allow_missing_key], opt_name)
|
|
83
|
-
check_hash_access_mode(value[:mode]) if value.key?(:mode)
|
|
84
|
-
Utils::CheckOptIsBool.call(value, :allow_missing_key)
|
|
85
|
-
else
|
|
86
|
-
raise SeregaError,
|
|
87
|
-
"Invalid delegate option :#{opt_name} => #{value.inspect}." \
|
|
88
|
-
" It must be a Boolean, a Symbol mode (:symbol, :string)" \
|
|
89
|
-
" or a Hash with :mode and :allow_missing_key keys"
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def check_hash_access_mode(mode)
|
|
94
|
-
return true if AttributeValueResolvers::HashAccessResolver::MODES.include?(mode)
|
|
95
|
-
|
|
96
|
-
raise SeregaError, "Invalid :hash_access mode #{mode.inspect}. Allowed modes: :symbol, :string"
|
|
49
|
+
Utils::CheckHashAccessValue.call(delegate_opts, :to_hash_access)
|
|
50
|
+
Utils::CheckHashAccessValue.call(delegate_opts, :hash_access)
|
|
97
51
|
end
|
|
98
52
|
|
|
99
53
|
def check_opt_delegate_extra_opts(delegate_opts)
|
|
100
54
|
Utils::CheckAllowedKeys.call(delegate_opts, %i[to method allow_nil to_hash_access hash_access], :delegate)
|
|
101
55
|
end
|
|
102
|
-
|
|
103
|
-
def check_usage_with_other_params(opts)
|
|
104
|
-
raise SeregaError, "Option :delegate can not be used together with option :method" if opts.key?(:method)
|
|
105
|
-
raise SeregaError, "Option :delegate can not be used together with option :const" if opts.key?(:const)
|
|
106
|
-
raise SeregaError, "Option :delegate can not be used together with option :value" if opts.key?(:value)
|
|
107
|
-
raise SeregaError, "Option :delegate can not be used together with option :batch" if opts.key?(:batch)
|
|
108
|
-
end
|
|
109
56
|
end
|
|
110
57
|
end
|
|
111
58
|
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Serega
|
|
4
|
+
module SeregaValidations # :nodoc:
|
|
5
|
+
module Attribute # :nodoc:
|
|
6
|
+
#
|
|
7
|
+
# Validator for attribute :format option
|
|
8
|
+
#
|
|
9
|
+
class CheckOptFormat # :nodoc:
|
|
10
|
+
class << self
|
|
11
|
+
# Checks attribute :format option is the name of an added formatter
|
|
12
|
+
# or a valid formatter
|
|
13
|
+
def call(opts, serializer_class)
|
|
14
|
+
return unless opts.key?(:format)
|
|
15
|
+
|
|
16
|
+
formatter = opts[:format]
|
|
17
|
+
|
|
18
|
+
if formatter.is_a?(Symbol)
|
|
19
|
+
check_formatter_defined(serializer_class, formatter)
|
|
20
|
+
else
|
|
21
|
+
CheckFormatter.call(nil, formatter)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def check_formatter_defined(serializer_class, formatter)
|
|
28
|
+
return if serializer_class.formatters.key?(formatter)
|
|
29
|
+
|
|
30
|
+
raise SeregaError, "Formatter `#{formatter.inspect}` was not defined"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -1,78 +1,30 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Serega
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
# @private
|
|
7
|
-
module Attribute
|
|
4
|
+
module SeregaValidations # :nodoc:
|
|
5
|
+
module Attribute # :nodoc:
|
|
8
6
|
#
|
|
9
7
|
# Attribute `:hash_access` option validator
|
|
10
8
|
#
|
|
11
|
-
#
|
|
12
|
-
class CheckOptHashAccess
|
|
9
|
+
class CheckOptHashAccess # :nodoc:
|
|
13
10
|
class << self
|
|
14
|
-
#
|
|
15
11
|
# Checks attribute :hash_access option
|
|
16
|
-
#
|
|
17
|
-
# @param opts [Hash] Attribute options
|
|
18
|
-
#
|
|
19
|
-
# @raise [SeregaError] Attribute validation error
|
|
20
|
-
#
|
|
21
|
-
# @return [void]
|
|
22
|
-
#
|
|
23
12
|
def call(opts)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
value = opts[:hash_access]
|
|
27
|
-
check_value(value)
|
|
28
|
-
check_usage_with_other_params(opts) if value
|
|
13
|
+
Utils::CheckHashAccessValue.call(opts, :hash_access)
|
|
14
|
+
check_usage_with_delegate(opts) if opts[:hash_access]
|
|
29
15
|
end
|
|
30
16
|
|
|
31
17
|
private
|
|
32
18
|
|
|
33
|
-
def check_value(value)
|
|
34
|
-
case value
|
|
35
|
-
when true, false then nil
|
|
36
|
-
when Symbol then check_mode(value)
|
|
37
|
-
when Hash
|
|
38
|
-
Utils::CheckAllowedKeys.call(value, %i[mode allow_missing_key], :hash_access)
|
|
39
|
-
check_mode(value[:mode]) if value.key?(:mode)
|
|
40
|
-
check_allow_missing_key(value[:allow_missing_key]) if value.key?(:allow_missing_key)
|
|
41
|
-
else
|
|
42
|
-
raise SeregaError,
|
|
43
|
-
"Invalid option :hash_access => #{value.inspect}." \
|
|
44
|
-
" It must be a Boolean, a Symbol mode (:symbol, :string)" \
|
|
45
|
-
" or a Hash with :mode and :allow_missing_key keys"
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def check_mode(mode)
|
|
50
|
-
return if AttributeValueResolvers::HashAccessResolver::MODES.include?(mode)
|
|
51
|
-
|
|
52
|
-
raise SeregaError, "Invalid :hash_access mode #{mode.inspect}. Allowed modes: :symbol, :string"
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def check_allow_missing_key(allow_missing_key)
|
|
56
|
-
return if allow_missing_key == true || allow_missing_key == false
|
|
57
|
-
|
|
58
|
-
raise SeregaError, "Invalid :hash_access option :allow_missing_key => #{allow_missing_key.inspect}. Must be a Boolean"
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# The :const, :value and :batch options do not read the serialized
|
|
62
|
-
# object by attribute name, so hash access can not affect them.
|
|
63
19
|
# Delegated attributes configure hash access per step with the
|
|
64
20
|
# `delegate: {to_hash_access:, hash_access:}` sub-options.
|
|
65
|
-
def
|
|
66
|
-
|
|
67
|
-
raise SeregaError, "Option :hash_access can not be used together with option :value" if opts.key?(:value)
|
|
68
|
-
raise SeregaError, "Option :hash_access can not be used together with option :batch" if opts.key?(:batch)
|
|
21
|
+
def check_usage_with_delegate(opts)
|
|
22
|
+
return unless opts.key?(:delegate)
|
|
69
23
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
" :hash_access (final step) sub-options instead"
|
|
75
|
-
end
|
|
24
|
+
raise SeregaError,
|
|
25
|
+
"Option :hash_access can not be used together with option :delegate." \
|
|
26
|
+
" Use the delegate :to_hash_access (intermediate step) and" \
|
|
27
|
+
" :hash_access (final step) sub-options instead"
|
|
76
28
|
end
|
|
77
29
|
end
|
|
78
30
|
end
|
|
@@ -1,24 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Serega
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
# @private
|
|
7
|
-
module Attribute
|
|
4
|
+
module SeregaValidations # :nodoc:
|
|
5
|
+
module Attribute # :nodoc:
|
|
8
6
|
#
|
|
9
7
|
# Attribute `:hide` option validator
|
|
10
8
|
#
|
|
11
|
-
#
|
|
12
|
-
class CheckOptHide
|
|
13
|
-
#
|
|
9
|
+
class CheckOptHide # :nodoc:
|
|
14
10
|
# Checks attribute :hide option
|
|
15
|
-
#
|
|
16
|
-
# @param opts [Hash] Attribute options
|
|
17
|
-
#
|
|
18
|
-
# @raise [SeregaError] SeregaError that option has invalid value
|
|
19
|
-
#
|
|
20
|
-
# @return [void]
|
|
21
|
-
#
|
|
22
11
|
def self.call(opts)
|
|
23
12
|
Utils::CheckOptIsBool.call(opts, :hide)
|
|
24
13
|
end
|
|
@@ -1,35 +1,33 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Serega
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
# @private
|
|
7
|
-
module Attribute
|
|
4
|
+
module SeregaValidations # :nodoc:
|
|
5
|
+
module Attribute # :nodoc:
|
|
8
6
|
#
|
|
9
7
|
# Attribute `:many` option validator
|
|
10
8
|
#
|
|
11
|
-
#
|
|
12
|
-
class CheckOptMany
|
|
9
|
+
class CheckOptMany # :nodoc:
|
|
13
10
|
class << self
|
|
14
|
-
#
|
|
15
11
|
# Checks attribute :many option
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
#
|
|
24
|
-
def call(opts, block = nil)
|
|
25
|
-
return unless opts.key?(:many)
|
|
26
|
-
|
|
27
|
-
check_many_option_makes_sence(opts, block)
|
|
28
|
-
Utils::CheckOptIsBool.call(opts, :many)
|
|
12
|
+
def call(opts, block = nil, required = false)
|
|
13
|
+
if opts.key?(:many)
|
|
14
|
+
check_many_option_makes_sence(opts, block)
|
|
15
|
+
Utils::CheckOptIsBool.call(opts, :many)
|
|
16
|
+
elsif required
|
|
17
|
+
check_many_option_not_required(opts, block)
|
|
18
|
+
end
|
|
29
19
|
end
|
|
30
20
|
|
|
31
21
|
private
|
|
32
22
|
|
|
23
|
+
def check_many_option_not_required(opts, block)
|
|
24
|
+
return if !opts[:serializer] && !block
|
|
25
|
+
|
|
26
|
+
raise SeregaError,
|
|
27
|
+
"Attribute option :many [Boolean] must be provided" \
|
|
28
|
+
" for attributes with :serializer option or a block"
|
|
29
|
+
end
|
|
30
|
+
|
|
33
31
|
def check_many_option_makes_sence(opts, block)
|
|
34
32
|
return if many_option_makes_sence?(opts, block)
|
|
35
33
|
|
|
@@ -1,39 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Serega
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
# @private
|
|
7
|
-
module Attribute
|
|
4
|
+
module SeregaValidations # :nodoc:
|
|
5
|
+
module Attribute # :nodoc:
|
|
8
6
|
#
|
|
9
7
|
# Attribute `:method` option validator
|
|
10
8
|
#
|
|
11
|
-
#
|
|
12
|
-
class CheckOptMethod
|
|
9
|
+
class CheckOptMethod # :nodoc:
|
|
13
10
|
class << self
|
|
14
|
-
#
|
|
15
11
|
# Checks attribute :method option
|
|
16
|
-
#
|
|
17
|
-
# @param opts [Hash] Attribute options
|
|
18
|
-
#
|
|
19
|
-
# @raise [SeregaError] SeregaError that option has invalid value
|
|
20
|
-
#
|
|
21
|
-
# @return [void]
|
|
22
|
-
#
|
|
23
12
|
def call(opts)
|
|
24
|
-
return unless opts.key?(:method)
|
|
25
|
-
|
|
26
|
-
check_usage_with_other_params(opts)
|
|
27
13
|
Utils::CheckOptIsStringOrSymbol.call(opts, :method)
|
|
28
14
|
end
|
|
29
|
-
|
|
30
|
-
private
|
|
31
|
-
|
|
32
|
-
def check_usage_with_other_params(opts)
|
|
33
|
-
raise SeregaError, "Option :method can not be used together with option :const" if opts.key?(:const)
|
|
34
|
-
raise SeregaError, "Option :method can not be used together with option :value" if opts.key?(:value)
|
|
35
|
-
raise SeregaError, "Option :method can not be used together with option :batch" if opts.key?(:batch)
|
|
36
|
-
end
|
|
37
15
|
end
|
|
38
16
|
end
|
|
39
17
|
end
|
|
@@ -1,40 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Serega
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
# @private
|
|
7
|
-
module Attribute
|
|
4
|
+
module SeregaValidations # :nodoc:
|
|
5
|
+
module Attribute # :nodoc:
|
|
8
6
|
#
|
|
9
7
|
# Validator for attribute :preload option
|
|
10
8
|
#
|
|
11
|
-
#
|
|
12
|
-
class CheckOptPreload
|
|
9
|
+
class CheckOptPreload # :nodoc:
|
|
13
10
|
class << self
|
|
14
|
-
#
|
|
15
11
|
# Checks :preload option
|
|
16
|
-
#
|
|
17
|
-
# @param opts [Hash] Attribute options
|
|
18
|
-
#
|
|
19
|
-
# @raise [SeregaError] validation error
|
|
20
|
-
#
|
|
21
|
-
# @return [void]
|
|
22
12
|
def call(opts)
|
|
23
|
-
return unless opts.key?(:preload)
|
|
24
|
-
|
|
25
|
-
check_opt_preload(opts)
|
|
26
|
-
check_usage_with_other_params(opts)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
private
|
|
30
|
-
|
|
31
|
-
def check_opt_preload(opts)
|
|
32
13
|
raise SeregaError, "Option :preload value can not be `true`" if opts[:preload] == true
|
|
33
14
|
end
|
|
34
|
-
|
|
35
|
-
def check_usage_with_other_params(opts)
|
|
36
|
-
raise SeregaError, "Option :preload can not be used together with option :const" if opts.key?(:const)
|
|
37
|
-
end
|
|
38
15
|
end
|
|
39
16
|
end
|
|
40
17
|
end
|