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.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +124 -1207
  3. data/VERSION +1 -1
  4. data/lib/serega/attribute.rb +186 -131
  5. data/lib/serega/attribute_normalizer.rb +164 -345
  6. data/lib/serega/attribute_normalizers/batch.rb +45 -0
  7. data/lib/serega/attribute_normalizers/block.rb +81 -0
  8. data/lib/serega/attribute_normalizers/delegate.rb +34 -0
  9. data/lib/serega/attribute_normalizers/hash_access.rb +37 -0
  10. data/lib/serega/attribute_normalizers/preloads.rb +46 -0
  11. data/lib/serega/attribute_value_resolvers/batch.rb +5 -54
  12. data/lib/serega/attribute_value_resolvers/const.rb +2 -24
  13. data/lib/serega/attribute_value_resolvers/delegate.rb +17 -28
  14. data/lib/serega/attribute_value_resolvers/hash_access.rb +34 -52
  15. data/lib/serega/attribute_value_resolvers/keyword.rb +10 -25
  16. data/lib/serega/attribute_values.rb +46 -0
  17. data/lib/serega/batch_loader.rb +37 -0
  18. data/lib/serega/conditions.rb +56 -0
  19. data/lib/serega/config.rb +105 -144
  20. data/lib/serega/engine/pulls.rb +64 -0
  21. data/lib/serega/engine/run.rb +106 -0
  22. data/lib/serega/errors.rb +36 -8
  23. data/lib/serega/formatter.rb +98 -0
  24. data/lib/serega/plan/cache.rb +96 -0
  25. data/lib/serega/plan/per_ractor_cache.rb +23 -0
  26. data/lib/serega/plan.rb +101 -128
  27. data/lib/serega/plan_point.rb +44 -151
  28. data/lib/serega/plugins/activerecord_preloads/activerecord_preloads.rb +13 -80
  29. data/lib/serega/plugins/activerecord_preloads/lib/preloader.rb +8 -75
  30. data/lib/serega/plugins/context_metadata/context_metadata.rb +40 -123
  31. data/lib/serega/plugins/metadata/check_params.rb +80 -0
  32. data/lib/serega/plugins/metadata/meta_attribute.rb +40 -79
  33. data/lib/serega/plugins/metadata/metadata.rb +40 -168
  34. data/lib/serega/plugins/root/root.rb +91 -235
  35. data/lib/serega/plugins.rb +16 -49
  36. data/lib/serega/presenter.rb +61 -19
  37. data/lib/serega/result_builder.rb +68 -0
  38. data/lib/serega/result_code.rb +203 -0
  39. data/lib/serega/shareable.rb +52 -0
  40. data/lib/serega/source_group.rb +187 -0
  41. data/lib/serega/utils/collection_detector.rb +19 -13
  42. data/lib/serega/utils/deep_merge.rb +26 -0
  43. data/lib/serega/utils/enum_deep_dup.rb +10 -16
  44. data/lib/serega/utils/enum_deep_freeze.rb +8 -14
  45. data/lib/serega/utils/method_signature.rb +6 -15
  46. data/lib/serega/utils/parse_string_modifiers.rb +63 -0
  47. data/lib/serega/utils/ractor_local.rb +36 -0
  48. data/lib/serega/utils/serialized_attribute_error.rb +60 -20
  49. data/lib/serega/utils/to_hash.rb +5 -26
  50. data/lib/serega/validations/attribute/check_block.rb +3 -15
  51. data/lib/serega/validations/attribute/check_name.rb +4 -15
  52. data/lib/serega/validations/attribute/check_opt_base_serializer.rb +3 -15
  53. data/lib/serega/validations/attribute/check_opt_batch.rb +26 -56
  54. data/lib/serega/validations/attribute/check_opt_condition.rb +55 -0
  55. data/lib/serega/validations/attribute/check_opt_delegate.rb +10 -63
  56. data/lib/serega/validations/attribute/check_opt_format.rb +36 -0
  57. data/lib/serega/validations/attribute/check_opt_hash_access.rb +11 -59
  58. data/lib/serega/validations/attribute/check_opt_hide.rb +3 -14
  59. data/lib/serega/validations/attribute/check_opt_many.rb +18 -20
  60. data/lib/serega/validations/attribute/check_opt_method.rb +3 -25
  61. data/lib/serega/validations/attribute/check_opt_preload.rb +3 -26
  62. data/lib/serega/validations/attribute/check_opt_serializer.rb +4 -18
  63. data/lib/serega/validations/attribute/check_opt_value.rb +3 -21
  64. data/lib/serega/validations/check_attribute_params.rb +92 -71
  65. data/lib/serega/validations/check_batch_loader_params.rb +43 -62
  66. data/lib/serega/validations/check_formatter.rb +80 -0
  67. data/lib/serega/validations/check_serialize_keywords.rb +23 -0
  68. data/lib/serega/validations/initiate/check_modifiers.rb +14 -20
  69. data/lib/serega/validations/utils/check_allowed_keys.rb +3 -13
  70. data/lib/serega/validations/utils/check_hash_access_value.rb +44 -0
  71. data/lib/serega/validations/utils/check_opt_is_bool.rb +3 -13
  72. data/lib/serega/validations/utils/check_opt_is_hash.rb +3 -13
  73. data/lib/serega/validations/utils/check_opt_is_string_or_symbol.rb +3 -13
  74. data/lib/serega/version.rb +1 -4
  75. data/lib/serega.rb +459 -388
  76. data/sig/serega/plugins.rbs +49 -0
  77. data/sig/serega.rbs +142 -0
  78. metadata +42 -38
  79. data/lib/serega/data_builder.rb +0 -54
  80. data/lib/serega/engine/level.rb +0 -59
  81. data/lib/serega/engine/level_queue.rb +0 -56
  82. data/lib/serega/engine/loader.rb +0 -70
  83. data/lib/serega/helpers/serializer_class_helper.rb +0 -19
  84. data/lib/serega/object_serializer.rb +0 -125
  85. data/lib/serega/plugins/camel_case/camel_case.rb +0 -213
  86. data/lib/serega/plugins/depth_limit/depth_limit.rb +0 -206
  87. data/lib/serega/plugins/explicit_many_option/explicit_many_option.rb +0 -69
  88. data/lib/serega/plugins/explicit_many_option/validations/check_opt_many.rb +0 -38
  89. data/lib/serega/plugins/formatters/formatters.rb +0 -322
  90. data/lib/serega/plugins/if/if.rb +0 -287
  91. data/lib/serega/plugins/if/validations/check_opt_if.rb +0 -72
  92. data/lib/serega/plugins/if/validations/check_opt_if_value.rb +0 -77
  93. data/lib/serega/plugins/if/validations/check_opt_unless.rb +0 -72
  94. data/lib/serega/plugins/if/validations/check_opt_unless_value.rb +0 -77
  95. data/lib/serega/plugins/metadata/validations/check_block.rb +0 -47
  96. data/lib/serega/plugins/metadata/validations/check_opt_const.rb +0 -39
  97. data/lib/serega/plugins/metadata/validations/check_opt_hide_empty.rb +0 -35
  98. data/lib/serega/plugins/metadata/validations/check_opt_hide_nil.rb +0 -35
  99. data/lib/serega/plugins/metadata/validations/check_opt_value.rb +0 -61
  100. data/lib/serega/plugins/metadata/validations/check_opts.rb +0 -59
  101. data/lib/serega/plugins/metadata/validations/check_path.rb +0 -50
  102. data/lib/serega/plugins/string_modifiers/parse_string_modifiers.rb +0 -111
  103. data/lib/serega/plugins/string_modifiers/string_modifiers.rb +0 -63
  104. data/lib/serega/utils/symbol_name.rb +0 -39
  105. data/lib/serega/validations/attribute/check_opt_const.rb +0 -40
  106. data/lib/serega/validations/check_initiate_params.rb +0 -57
  107. 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
- # @private
5
- module SeregaValidations
6
- # @private
7
- module Attribute
4
+ module SeregaValidations # :nodoc:
5
+ module Attribute # :nodoc:
8
6
  #
9
7
  # Attribute `name` parameter validator
10
8
  #
11
- # @private
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 = SeregaUtils::SymbolName.call(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
- # @private
5
- module SeregaValidations
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
- # @private
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
- # @private
5
- module SeregaValidations
6
- # @private
7
- module Attribute
4
+ module SeregaValidations # :nodoc:
5
+ module Attribute # :nodoc:
8
6
  #
9
7
  # Attribute `:batch` option validator
10
8
  #
11
- # @private
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
- check_opt_batch(opts, serializer_class)
27
- check_usage_with_other_params(opts)
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
- def check_opt_batch(opts, serializer_class)
33
- batch_opts = opts[:batch]
34
- return if batch_opts == true
35
- return if batch_opts.respond_to?(:call)
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
- check_loader_exists?(serializer_class, batch_loader_name)
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 check_opt_batch_id(batch_opts)
57
- return unless batch_opts.key?(:id)
33
+ def check_id(batch)
34
+ return unless batch.key?(:id)
58
35
 
59
- id_method_name = batch_opts[:id]
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
- def check_loader_exists?(serializer_class, value)
66
- values = Array(value)
67
- values.each do |batch_loader_name|
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 check_opt_batch_extra_opts(batch_opts)
75
- Utils::CheckAllowedKeys.call(batch_opts, %i[use id], :batch)
76
- end
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
- # @private
5
- module SeregaValidations
6
- # @private
7
- module Attribute
4
+ module SeregaValidations # :nodoc:
5
+ module Attribute # :nodoc:
8
6
  #
9
7
  # Attribute `:delegate` option validator
10
8
  #
11
- # @private
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. Accepts the same
63
- # forms as the final (:method) step.
64
- def check_opt_delegate_to_hash_access(delegate_opts)
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
- check_hash_access_value(delegate_opts, :hash_access)
72
- end
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
- # @private
5
- module SeregaValidations
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
- # @private
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
- return unless opts.key?(:hash_access)
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 check_usage_with_other_params(opts)
66
- raise SeregaError, "Option :hash_access can not be used together with option :const" if opts.key?(:const)
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
- if opts.key?(:delegate)
71
- raise SeregaError,
72
- "Option :hash_access can not be used together with option :delegate." \
73
- " Use the delegate :to_hash_access (intermediate step) and" \
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
- # @private
5
- module SeregaValidations
6
- # @private
7
- module Attribute
4
+ module SeregaValidations # :nodoc:
5
+ module Attribute # :nodoc:
8
6
  #
9
7
  # Attribute `:hide` option validator
10
8
  #
11
- # @private
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
- # @private
5
- module SeregaValidations
6
- # @private
7
- module Attribute
4
+ module SeregaValidations # :nodoc:
5
+ module Attribute # :nodoc:
8
6
  #
9
7
  # Attribute `:many` option validator
10
8
  #
11
- # @private
12
- class CheckOptMany
9
+ class CheckOptMany # :nodoc:
13
10
  class << self
14
- #
15
11
  # Checks attribute :many option
16
- #
17
- # @param opts [Hash] Attribute options
18
- # @param block [nil, Proc] Attribute block
19
- #
20
- # @raise [SeregaError] SeregaError that option has invalid value
21
- #
22
- # @return [void]
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
- # @private
5
- module SeregaValidations
6
- # @private
7
- module Attribute
4
+ module SeregaValidations # :nodoc:
5
+ module Attribute # :nodoc:
8
6
  #
9
7
  # Attribute `:method` option validator
10
8
  #
11
- # @private
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
- # @private
5
- module SeregaValidations
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
- # @private
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