serega 0.15.0 → 0.17.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +121 -22
  3. data/VERSION +1 -1
  4. data/lib/serega/attribute.rb +5 -5
  5. data/lib/serega/attribute_normalizer.rb +29 -11
  6. data/lib/serega/config.rb +1 -1
  7. data/lib/serega/object_serializer.rb +1 -1
  8. data/lib/serega/plan.rb +11 -11
  9. data/lib/serega/plan_point.rb +5 -5
  10. data/lib/serega/plugins/activerecord_preloads/activerecord_preloads.rb +1 -1
  11. data/lib/serega/plugins/batch/batch.rb +15 -15
  12. data/lib/serega/plugins/batch/lib/batch_config.rb +11 -8
  13. data/lib/serega/plugins/batch/lib/modules/attribute_normalizer.rb +26 -11
  14. data/lib/serega/plugins/batch/lib/validations/check_batch_opt_key.rb +5 -35
  15. data/lib/serega/plugins/batch/lib/validations/check_batch_opt_loader.rb +5 -35
  16. data/lib/serega/plugins/batch/lib/validations/check_opt_batch.rb +2 -2
  17. data/lib/serega/plugins/camel_case/camel_case.rb +195 -0
  18. data/lib/serega/plugins/depth_limit/depth_limit.rb +185 -0
  19. data/lib/serega/plugins/explicit_many_option/explicit_many_option.rb +1 -1
  20. data/lib/serega/plugins/formatters/formatters.rb +88 -14
  21. data/lib/serega/plugins/if/if.rb +47 -23
  22. data/lib/serega/plugins/if/validations/check_opt_if.rb +4 -36
  23. data/lib/serega/plugins/if/validations/check_opt_if_value.rb +7 -39
  24. data/lib/serega/plugins/if/validations/check_opt_unless.rb +4 -45
  25. data/lib/serega/plugins/if/validations/check_opt_unless_value.rb +7 -39
  26. data/lib/serega/plugins/metadata/meta_attribute.rb +21 -5
  27. data/lib/serega/plugins/metadata/metadata.rb +22 -13
  28. data/lib/serega/plugins/metadata/validations/check_block.rb +10 -10
  29. data/lib/serega/plugins/metadata/validations/check_opt_const.rb +38 -0
  30. data/lib/serega/plugins/metadata/validations/check_opt_value.rb +61 -0
  31. data/lib/serega/plugins/metadata/validations/check_opts.rb +24 -10
  32. data/lib/serega/plugins/preloads/lib/modules/attribute_normalizer.rb +1 -1
  33. data/lib/serega/plugins/preloads/lib/preload_paths.rb +12 -5
  34. data/lib/serega/plugins/preloads/lib/preloads_constructor.rb +1 -1
  35. data/lib/serega/plugins/preloads/preloads.rb +12 -12
  36. data/lib/serega/plugins/root/root.rb +1 -1
  37. data/lib/serega/plugins/string_modifiers/string_modifiers.rb +1 -1
  38. data/lib/serega/utils/params_count.rb +50 -0
  39. data/lib/serega/utils/to_hash.rb +1 -1
  40. data/lib/serega/validations/attribute/check_block.rb +4 -5
  41. data/lib/serega/validations/attribute/check_opt_const.rb +1 -1
  42. data/lib/serega/validations/attribute/check_opt_delegate.rb +9 -4
  43. data/lib/serega/validations/attribute/{check_opt_key.rb → check_opt_method.rb} +8 -8
  44. data/lib/serega/validations/attribute/check_opt_value.rb +17 -13
  45. data/lib/serega/validations/check_attribute_params.rb +3 -2
  46. data/lib/serega/validations/check_initiate_params.rb +1 -1
  47. data/lib/serega/validations/check_serialize_params.rb +1 -1
  48. data/lib/serega/validations/utils/check_allowed_keys.rb +4 -2
  49. data/lib/serega/validations/utils/check_extra_keyword_arg.rb +33 -0
  50. data/lib/serega.rb +26 -11
  51. metadata +10 -4
@@ -56,15 +56,16 @@ class Serega
56
56
  # @return [void]
57
57
  #
58
58
  def self.load_plugin(serializer_class, **_opts)
59
- require_relative "./validations/check_opt_if"
60
- require_relative "./validations/check_opt_if_value"
61
- require_relative "./validations/check_opt_unless"
62
- require_relative "./validations/check_opt_unless_value"
59
+ require_relative "validations/check_opt_if"
60
+ require_relative "validations/check_opt_if_value"
61
+ require_relative "validations/check_opt_unless"
62
+ require_relative "validations/check_opt_unless_value"
63
63
 
64
- serializer_class::SeregaAttribute.include(SeregaAttributeInstanceMethods)
64
+ serializer_class::SeregaAttribute.include(AttributeInstanceMethods)
65
+ serializer_class::SeregaAttributeNormalizer.include(AttributeNormalizerInstanceMethods)
65
66
  serializer_class::SeregaPlanPoint.include(PlanPointInstanceMethods)
66
67
  serializer_class::CheckAttributeParams.include(CheckAttributeParamsInstanceMethods)
67
- serializer_class::SeregaObjectSerializer.include(SeregaObjectSerializerInstanceMethods)
68
+ serializer_class::SeregaObjectSerializer.include(ObjectSerializerInstanceMethods)
68
69
  end
69
70
 
70
71
  #
@@ -79,12 +80,47 @@ class Serega
79
80
  serializer_class.config.attribute_keys << :if << :if_value << :unless << :unless_value
80
81
  end
81
82
 
83
+ #
84
+ # SeregaAttributeNormalizer additional/patched instance methods
85
+ #
86
+ # @see SeregaAttributeNormalizer::AttributeInstanceMethods
87
+ #
88
+ module AttributeNormalizerInstanceMethods
89
+ #
90
+ # Returns prepared attribute :if_options.
91
+ #
92
+ # @return [Hash] prepared options for :if plugin
93
+ #
94
+ def if_options
95
+ @if_options ||= {
96
+ if: prepare_if_option(init_opts[:if]),
97
+ unless: prepare_if_option(init_opts[:unless]),
98
+ if_value: prepare_if_option(init_opts[:if_value]),
99
+ unless_value: prepare_if_option(init_opts[:unless_value])
100
+ }.freeze
101
+ end
102
+
103
+ private
104
+
105
+ def prepare_if_option(if_option)
106
+ return unless if_option
107
+ return proc { |val| val.public_send(if_option) } if if_option.is_a?(Symbol)
108
+
109
+ params_count = SeregaUtils::ParamsCount.call(if_option, max_count: 2)
110
+ case params_count
111
+ when 0 then proc { if_option.call }
112
+ when 1 then proc { |obj| if_option.call(obj) }
113
+ else if_option
114
+ end
115
+ end
116
+ end
117
+
82
118
  #
83
119
  # SeregaAttribute additional/patched instance methods
84
120
  #
85
121
  # @see Serega::SeregaAttribute
86
122
  #
87
- module SeregaAttributeInstanceMethods
123
+ module AttributeInstanceMethods
88
124
  # @return provided :if options
89
125
  attr_reader :opt_if
90
126
 
@@ -92,7 +128,7 @@ class Serega
92
128
 
93
129
  def set_normalized_vars(normalizer)
94
130
  super
95
- @opt_if = initials[:opts].slice(:if, :if_value, :unless, :unless_value).freeze
131
+ @opt_if = normalizer.if_options
96
132
  end
97
133
  end
98
134
 
@@ -125,20 +161,8 @@ class Serega
125
161
  opt_unless = attribute.opt_if[opt_unless_name]
126
162
  return true if opt_if.nil? && opt_unless.nil?
127
163
 
128
- res_if =
129
- case opt_if
130
- when NilClass then true
131
- when Symbol then obj.public_send(opt_if)
132
- else opt_if.call(obj, ctx)
133
- end
134
-
135
- res_unless =
136
- case opt_unless
137
- when NilClass then true
138
- when Symbol then !obj.public_send(opt_unless)
139
- else !opt_unless.call(obj, ctx)
140
- end
141
-
164
+ res_if = opt_if ? opt_if.call(obj, ctx) : true
165
+ res_unless = opt_unless ? !opt_unless.call(obj, ctx) : true
142
166
  res_if && res_unless
143
167
  end
144
168
  end
@@ -166,7 +190,7 @@ class Serega
166
190
  #
167
191
  # @see Serega::SeregaObjectSerializer
168
192
  #
169
- module SeregaObjectSerializerInstanceMethods
193
+ module ObjectSerializerInstanceMethods
170
194
  private
171
195
 
172
196
  def serialize_point(object, point, _container)
@@ -27,48 +27,16 @@ class Serega
27
27
 
28
28
  def check_type(value)
29
29
  return if value.is_a?(Symbol)
30
-
31
30
  raise SeregaError, must_be_callable unless value.respond_to?(:call)
32
31
 
33
- if value.is_a?(Proc)
34
- check_block(value)
35
- else
36
- check_callable(value)
37
- end
38
- end
39
-
40
- def check_block(block)
41
- return if valid_parameters?(block, accepted_count: 0..2)
32
+ SeregaValidations::Utils::CheckExtraKeywordArg.call(value, ":if option")
33
+ params_count = SeregaUtils::ParamsCount.call(value, max_count: 2)
42
34
 
43
- raise SeregaError, block_parameters_error
44
- end
45
-
46
- def check_callable(callable)
47
- return if valid_parameters?(callable.method(:call), accepted_count: 2..2)
48
-
49
- raise SeregaError, callable_parameters_error
50
- end
51
-
52
- def valid_parameters?(data, accepted_count:)
53
- params = data.parameters
54
- accepted_count.include?(params.count) && valid_parameters_types?(params)
55
- end
56
-
57
- def valid_parameters_types?(params)
58
- params.all? do |param|
59
- type = param[0]
60
- (type == :req) || (type == :opt)
35
+ if params_count > 2
36
+ raise SeregaError, "Option :if value should have up to 2 parameters (object, context)"
61
37
  end
62
38
  end
63
39
 
64
- def block_parameters_error
65
- "Invalid attribute option :if. When it is a Proc it can have maximum two regular parameters (object, context)"
66
- end
67
-
68
- def callable_parameters_error
69
- "Invalid attribute option :if. When it is a callable object it must have two regular parameters (object, context)"
70
- end
71
-
72
40
  def must_be_callable
73
41
  "Invalid attribute option :if. It must be a Symbol, a Proc or respond to :call"
74
42
  end
@@ -26,54 +26,22 @@ class Serega
26
26
 
27
27
  private
28
28
 
29
- def check_type(value)
30
- return if value.is_a?(Symbol)
31
-
32
- raise SeregaError, must_be_callable unless value.respond_to?(:call)
33
-
34
- if value.is_a?(Proc)
35
- check_block(value)
36
- else
37
- check_callable(value)
38
- end
39
- end
40
-
41
29
  def check_usage_with_other_params(opts)
42
30
  raise SeregaError, "Option :if_value can not be used together with option :serializer" if opts.key?(:serializer)
43
31
  end
44
32
 
45
- def check_block(block)
46
- return if valid_parameters?(block, accepted_count: 0..2)
47
-
48
- raise SeregaError, block_parameters_error
49
- end
50
-
51
- def check_callable(callable)
52
- return if valid_parameters?(callable.method(:call), accepted_count: 2..2)
53
-
54
- raise SeregaError, callable_parameters_error
55
- end
33
+ def check_type(value)
34
+ return if value.is_a?(Symbol)
35
+ raise SeregaError, must_be_callable unless value.respond_to?(:call)
56
36
 
57
- def valid_parameters?(data, accepted_count:)
58
- params = data.parameters
59
- accepted_count.include?(params.count) && valid_parameters_types?(params)
60
- end
37
+ SeregaValidations::Utils::CheckExtraKeywordArg.call(value, ":if_value option")
38
+ params_count = SeregaUtils::ParamsCount.call(value, max_count: 2)
61
39
 
62
- def valid_parameters_types?(params)
63
- params.all? do |param|
64
- type = param[0]
65
- (type == :req) || (type == :opt)
40
+ if params_count > 2
41
+ raise SeregaError, "Option :if_value value should have up to 2 parameters (value, context)"
66
42
  end
67
43
  end
68
44
 
69
- def block_parameters_error
70
- "Invalid attribute option :if_value. When it is a Proc it can have maximum two regular parameters (object, context)"
71
- end
72
-
73
- def callable_parameters_error
74
- "Invalid attribute option :if_value. When it is a callable object it must have two regular parameters (object, context)"
75
- end
76
-
77
45
  def must_be_callable
78
46
  "Invalid attribute option :if_value. It must be a Symbol, a Proc or respond to :call"
79
47
  end
@@ -25,59 +25,18 @@ class Serega
25
25
 
26
26
  private
27
27
 
28
- #
29
- # Checks attribute :unless option
30
- #
31
- # @param value [nil, Symbol, Proc, #call] Attribute :unless option
32
- #
33
- # @raise [SeregaError] validation error
34
- #
35
- # @return [void]
36
- #
37
28
  def check_type(value)
38
29
  return if value.is_a?(Symbol)
39
-
40
30
  raise SeregaError, must_be_callable unless value.respond_to?(:call)
41
31
 
42
- if value.is_a?(Proc)
43
- check_block(value)
44
- else
45
- check_callable(value)
46
- end
47
- end
32
+ SeregaValidations::Utils::CheckExtraKeywordArg.call(value, ":unless option")
33
+ params_count = SeregaUtils::ParamsCount.call(value, max_count: 2)
48
34
 
49
- def check_block(block)
50
- return if valid_parameters?(block, accepted_count: 0..2)
51
-
52
- raise SeregaError, block_parameters_error
53
- end
54
-
55
- def check_callable(callable)
56
- return if valid_parameters?(callable.method(:call), accepted_count: 2..2)
57
-
58
- raise SeregaError, callable_parameters_error
59
- end
60
-
61
- def valid_parameters?(data, accepted_count:)
62
- params = data.parameters
63
- accepted_count.include?(params.count) && valid_parameters_types?(params)
64
- end
65
-
66
- def valid_parameters_types?(params)
67
- params.all? do |param|
68
- type = param[0]
69
- (type == :req) || (type == :opt)
35
+ if params_count > 2
36
+ raise SeregaError, "Option :unless value should have up to 2 parameters (object, context)"
70
37
  end
71
38
  end
72
39
 
73
- def block_parameters_error
74
- "Invalid attribute option :unless. When it is a Proc it can have maximum two regular parameters (object, context)"
75
- end
76
-
77
- def callable_parameters_error
78
- "Invalid attribute option :unless. When it is a callable object it must have two regular parameters (object, context)"
79
- end
80
-
81
40
  def must_be_callable
82
41
  "Invalid attribute option :unless. It must be a Symbol, a Proc or respond to :call"
83
42
  end
@@ -26,54 +26,22 @@ class Serega
26
26
 
27
27
  private
28
28
 
29
- def check_type(value)
30
- return if value.is_a?(Symbol)
31
-
32
- raise SeregaError, must_be_callable unless value.respond_to?(:call)
33
-
34
- if value.is_a?(Proc)
35
- check_block(value)
36
- else
37
- check_callable(value)
38
- end
39
- end
40
-
41
29
  def check_usage_with_other_params(opts)
42
30
  raise SeregaError, "Option :unless_value can not be used together with option :serializer" if opts.key?(:serializer)
43
31
  end
44
32
 
45
- def check_block(block)
46
- return if valid_parameters?(block, accepted_count: 0..2)
47
-
48
- raise SeregaError, block_parameters_error
49
- end
50
-
51
- def check_callable(callable)
52
- return if valid_parameters?(callable.method(:call), accepted_count: 2..2)
53
-
54
- raise SeregaError, callable_parameters_error
55
- end
33
+ def check_type(value)
34
+ return if value.is_a?(Symbol)
35
+ raise SeregaError, must_be_callable unless value.respond_to?(:call)
56
36
 
57
- def valid_parameters?(data, accepted_count:)
58
- params = data.parameters
59
- accepted_count.include?(params.count) && valid_parameters_types?(params)
60
- end
37
+ SeregaValidations::Utils::CheckExtraKeywordArg.call(value, ":unless_value option")
38
+ params_count = SeregaUtils::ParamsCount.call(value, max_count: 2)
61
39
 
62
- def valid_parameters_types?(params)
63
- params.all? do |param|
64
- type = param[0]
65
- (type == :req) || (type == :opt)
40
+ if params_count > 2
41
+ raise SeregaError, "Option :unless_value value should have up to 2 parameters (value, context)"
66
42
  end
67
43
  end
68
44
 
69
- def block_parameters_error
70
- "Invalid attribute option :unless_value. When it is a Proc it can have maximum two regular parameters (object, context)"
71
- end
72
-
73
- def callable_parameters_error
74
- "Invalid attribute option :unless_value. When it is a callable object it must have two regular parameters (object, context)"
75
- end
76
-
77
45
  def must_be_callable
78
46
  "Invalid attribute option :unless_value. It must be a Symbol, a Proc or respond to :call"
79
47
  end
@@ -20,7 +20,7 @@ class Serega
20
20
  # @return [Proc] Meta attribute options
21
21
  attr_reader :opts
22
22
 
23
- # @return [Proc] Meta attribute originally added block
23
+ # @return [Proc,nil] Meta attribute originally added block
24
24
  attr_reader :block
25
25
 
26
26
  #
@@ -39,6 +39,7 @@ class Serega
39
39
  @path = SeregaUtils::EnumDeepDup.call(path)
40
40
  @opts = SeregaUtils::EnumDeepDup.call(opts)
41
41
  @block = block
42
+ @normalized_block = normalize_block(opts[:value], opts[:const], block)
42
43
  end
43
44
 
44
45
  #
@@ -50,19 +51,34 @@ class Serega
50
51
  # @return [Object] Serialized meta attribute value
51
52
  #
52
53
  def value(object, context)
53
- block.call(object, context)
54
+ normalized_block.call(object, context)
54
55
  end
55
56
 
56
57
  def hide?(value)
57
- (opts[:hide_nil] && value.nil?) || (opts[:hide_empty] && value.empty?)
58
+ (!!opts[:hide_nil] && value.nil?) || (!!opts[:hide_empty] && (value.nil? || (value.respond_to?(:empty?) && value.empty?)))
58
59
  end
59
60
 
60
61
  private
61
62
 
63
+ attr_reader :normalized_block
64
+
65
+ def normalize_block(value, const, block)
66
+ return proc { const } if const
67
+
68
+ callable = (value || block)
69
+ params_count = SeregaUtils::ParamsCount.call(callable, max_count: 2)
70
+
71
+ case params_count
72
+ when 0 then proc { callable.call }
73
+ when 1 then proc { |obj| callable.call(obj) }
74
+ else callable
75
+ end
76
+ end
77
+
62
78
  def check(path, opts, block)
63
79
  CheckPath.call(path) if check_attribute_name
64
- CheckOpts.call(opts, attribute_keys)
65
- CheckBlock.call(block)
80
+ CheckOpts.call(opts, block, attribute_keys)
81
+ CheckBlock.call(block) if block
66
82
  end
67
83
 
68
84
  def attribute_keys
@@ -10,17 +10,24 @@ class Serega
10
10
  # Adds ability to describe metadata that must be added to serialized response
11
11
  #
12
12
  # Added class-level method `:meta_attribute`, to define metadata, it accepts:
13
- # - *path [Array<Symbol>] - nested hash keys beginning from the root object.
14
- # - **options [Hash] - defaults are `hide_nil: false, hide_empty: false`
15
- # - &block [Proc] - describes value for current meta attribute
13
+ #
14
+ # - `*path` [Array of Symbols] - nested hash keys.
15
+ # - `**options` [Hash]
16
+ #
17
+ # - `:const` - describes metadata value (if it is constant)
18
+ # - `:value` - describes metadata value as any `#callable` instance
19
+ # - `:hide_nil` - does not show metadata key if value is nil, `false` by default
20
+ # - `:hide_empty`, does not show metadata key if value is nil or empty, `false` by default
21
+ #
22
+ # - `&block` [Proc] - describes value for current meta attribute
16
23
  #
17
24
  # @example
18
25
  # class AppSerializer < Serega
19
26
  # plugin :root
20
27
  # plugin :metadata
21
28
  #
22
- # meta_attribute(:version) { '1.2.3' }
23
- # meta_attribute(:ab_tests, :names) { %i[foo bar] }
29
+ # meta_attribute(:version, const: '1.2.3')
30
+ # meta_attribute(:ab_tests, :names, value: ABTests.new.method(:names))
24
31
  # meta_attribute(:meta, :paging, hide_nil: true) do |records, ctx|
25
32
  # next unless records.respond_to?(:total_count)
26
33
  #
@@ -28,7 +35,7 @@ class Serega
28
35
  # end
29
36
  # end
30
37
  #
31
- # AppSerializer.to_h(nil) # => {:data=>nil, :version=>"1.2.3", :ab_tests=>{:names=>[:foo, :bar]}}
38
+ # AppSerializer.to_h(nil) # => {:data=>nil, :version=>"1.2.3", :ab_tests=>{:names=> ... }}
32
39
  #
33
40
  module Metadata
34
41
  # @return [Symbol] Plugin name
@@ -62,12 +69,14 @@ class Serega
62
69
  serializer_class.include(InstanceMethods)
63
70
  serializer_class::SeregaConfig.include(ConfigInstanceMethods)
64
71
 
65
- require_relative "./meta_attribute"
66
- require_relative "./validations/check_block"
67
- require_relative "./validations/check_opt_hide_nil"
68
- require_relative "./validations/check_opt_hide_empty"
69
- require_relative "./validations/check_opts"
70
- require_relative "./validations/check_path"
72
+ require_relative "meta_attribute"
73
+ require_relative "validations/check_block"
74
+ require_relative "validations/check_opt_const"
75
+ require_relative "validations/check_opt_hide_nil"
76
+ require_relative "validations/check_opt_hide_empty"
77
+ require_relative "validations/check_opt_value"
78
+ require_relative "validations/check_opts"
79
+ require_relative "validations/check_path"
71
80
 
72
81
  meta_attribute_class = Class.new(MetaAttribute)
73
82
  meta_attribute_class.serializer_class = serializer_class
@@ -83,7 +92,7 @@ class Serega
83
92
  # @return [void]
84
93
  #
85
94
  def self.after_load_plugin(serializer_class, **_opts)
86
- serializer_class.config.opts[:metadata] = {attribute_keys: %i[path hide_nil hide_empty]}
95
+ serializer_class.config.opts[:metadata] = {attribute_keys: %i[const hide_nil hide_empty value]}
87
96
  end
88
97
 
89
98
  #
@@ -8,14 +8,10 @@ class Serega
8
8
  # Validator for meta_attribute block parameter
9
9
  #
10
10
  class CheckBlock
11
- ALLOWED_PARAM_TYPES = %i[opt req]
12
- private_constant :ALLOWED_PARAM_TYPES
13
-
14
11
  class << self
15
12
  #
16
13
  # Checks block provided with attribute
17
- # Block must have up to two arguments - object and context.
18
- # It should not have any *rest or **key arguments
14
+ # Block must have up to two arguments - object(s) and context.
19
15
  #
20
16
  # @example without arguments
21
17
  # metadata(:version) { CONSTANT_VERSION }
@@ -24,7 +20,7 @@ class Serega
24
20
  # metadata(:paging) { |scope| { { page: scope.page, per_page: scope.per_page, total_count: scope.total_count } }
25
21
  #
26
22
  # @example with two arguments
27
- # metadata(:paging) { |scope, context| { { ... } if context[:with_paging] }
23
+ # metadata(:paging) { |scope, context| { { ... } if context[:pagy] }
28
24
  #
29
25
  # @param block [Proc] Block that returns serialized meta attribute value
30
26
  #
@@ -33,12 +29,16 @@ class Serega
33
29
  # @return [void]
34
30
  #
35
31
  def call(block)
36
- raise SeregaError, "Block must be provided when defining meta attribute" unless block
32
+ SeregaValidations::Utils::CheckExtraKeywordArg.call(block, "block")
33
+ params_count = SeregaUtils::ParamsCount.call(block, max_count: 2)
34
+
35
+ raise SeregaError, block_error if params_count > 2
36
+ end
37
37
 
38
- params = block.parameters
39
- return if (params.count <= 2) && params.all? { |par| ALLOWED_PARAM_TYPES.include?(par[0]) }
38
+ private
40
39
 
41
- raise SeregaError, "Block can have maximum 2 regular parameters (no **keyword or *array args)"
40
+ def block_error
41
+ "Block can have maximum two parameters (object(s), context)"
42
42
  end
43
43
  end
44
44
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ module SeregaPlugins
5
+ module Metadata
6
+ class MetaAttribute
7
+ #
8
+ # MetaAttribute `:const` option validator
9
+ #
10
+ class CheckOptConst
11
+ class << self
12
+ #
13
+ # Checks meta_attribute :const option
14
+ #
15
+ # @param opts [Hash] MetaAttribute options
16
+ #
17
+ # @raise [SeregaError] validation error
18
+ #
19
+ # @return [void]
20
+ #
21
+ def call(opts, block = nil)
22
+ return unless opts.key?(:const)
23
+
24
+ check_usage_with_other_params(opts, block)
25
+ end
26
+
27
+ private
28
+
29
+ def check_usage_with_other_params(opts, block)
30
+ raise SeregaError, "Option :const can not be used together with option :value" if opts.key?(:value)
31
+ raise SeregaError, "Option :const can not be used together with block" if block
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ module SeregaPlugins
5
+ module Metadata
6
+ class MetaAttribute
7
+ #
8
+ # Validator for meta_attribute :value option
9
+ #
10
+ class CheckOptValue
11
+ class << self
12
+ #
13
+ # Checks attribute :value option
14
+ #
15
+ # @param opts [Hash] Attribute options
16
+ #
17
+ # @raise [SeregaError] SeregaError that option has invalid value
18
+ #
19
+ # @return [void]
20
+ #
21
+ def call(opts, block = nil)
22
+ return unless opts.key?(:value)
23
+
24
+ check_usage_with_other_params(opts, block)
25
+
26
+ check_value(opts[:value])
27
+ end
28
+
29
+ private
30
+
31
+ def check_usage_with_other_params(opts, block)
32
+ raise SeregaError, "Option :value can not be used together with option :const" if opts.key?(:const)
33
+ raise SeregaError, "Option :value can not be used together with block" if block
34
+ end
35
+
36
+ def check_value(value)
37
+ check_value_type(value)
38
+
39
+ SeregaValidations::Utils::CheckExtraKeywordArg.call(value, ":value option")
40
+ params_count = SeregaUtils::ParamsCount.call(value, max_count: 2)
41
+
42
+ raise SeregaError, params_count_error if params_count > 2
43
+ end
44
+
45
+ def check_value_type(value)
46
+ raise SeregaError, type_error if !value.is_a?(Proc) && !value.respond_to?(:call)
47
+ end
48
+
49
+ def type_error
50
+ "Option :value value must be a Proc or respond to #call"
51
+ end
52
+
53
+ def params_count_error
54
+ "Option :value value can have maximum 2 parameters (object(s), context)"
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end