serega 0.15.0 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
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