serega 0.41.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 (108) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +123 -1205
  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 +106 -145
  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 -145
  28. data/lib/serega/plugins/activerecord_preloads/activerecord_preloads.rb +14 -100
  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 +108 -0
  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 +480 -372
  76. data/sig/serega/plugins.rbs +49 -0
  77. data/sig/serega.rbs +142 -0
  78. metadata +43 -39
  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 -118
  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/presenter/presenter.rb +0 -242
  103. data/lib/serega/plugins/string_modifiers/parse_string_modifiers.rb +0 -111
  104. data/lib/serega/plugins/string_modifiers/string_modifiers.rb +0 -63
  105. data/lib/serega/utils/symbol_name.rb +0 -39
  106. data/lib/serega/validations/attribute/check_opt_const.rb +0 -40
  107. data/lib/serega/validations/check_initiate_params.rb +0 -57
  108. data/lib/serega/validations/check_serialize_params.rb +0 -54
@@ -1,26 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Serega
4
- # @private
5
- module SeregaUtils
4
+ module SeregaUtils # :nodoc:
6
5
  #
7
6
  # Utility to check if an object should be serialized as a collection.
8
7
  #
9
8
  # Hashes and Structs are Enumerable, but enumerate their own member
10
9
  # values, so they are treated as single objects.
11
10
  #
12
- # @private
13
- class CollectionDetector
11
+ class CollectionDetector # :nodoc:
12
+ # Number of classes a Hash of known classes keeps
13
+ MAX_KNOWN_CLASSES = 8
14
+
14
15
  class << self
15
- #
16
- # Checks if provided object is a collection of objects
17
- #
18
- # @param object [Object] Serialized object
19
- #
20
- # @return [Boolean] whether object should be serialized as a collection
21
- #
22
- def call(object)
23
- object.is_a?(Enumerable) && !object.is_a?(Hash) && !object.is_a?(Struct)
16
+ # Checks if provided object is a collection of objects. Remembers the
17
+ # answer for the class of the object in `known_classes`, up to
18
+ # MAX_KNOWN_CLASSES classes: `is_a?(Enumerable)` checks all
19
+ # ancestors of a class that does not include Enumerable.
20
+ def call(object, known_classes)
21
+ return true if object.instance_of?(Array)
22
+
23
+ object_class = object.class
24
+ collection = known_classes[object_class]
25
+ return collection unless collection.nil?
26
+
27
+ collection = object.is_a?(Enumerable) && !object.is_a?(Hash) && !object.is_a?(Struct)
28
+ known_classes[object_class] = collection if known_classes.size < MAX_KNOWN_CLASSES
29
+ collection
24
30
  end
25
31
  end
26
32
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ module SeregaUtils # :nodoc:
5
+ #
6
+ # Merges nested hashes
7
+ #
8
+ class DeepMerge # :nodoc:
9
+ class << self
10
+ # Merges `other` into `hash` in place. Nested hashes merge into new
11
+ # hashes, thus `other` stays unchanged. Other values of `other` win.
12
+ def call(hash, other)
13
+ hash.merge!(other) { |_key, this_val, other_val| merge_values(this_val, other_val) }
14
+ end
15
+
16
+ private
17
+
18
+ def merge_values(this_val, other_val)
19
+ return other_val unless this_val.is_a?(Hash) && other_val.is_a?(Hash)
20
+
21
+ this_val.merge(other_val) { |_key, this_nested, other_nested| merge_values(this_nested, other_nested) }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -4,23 +4,15 @@ class Serega
4
4
  #
5
5
  # Utilities
6
6
  #
7
- # @private
8
- module SeregaUtils
7
+ module SeregaUtils # :nodoc:
9
8
  #
10
- # Duplicates nested hashes and arrays
11
- # It does not duplicate any non-Array and non-Hash values
9
+ # Duplicates nested hashes, arrays and strings
10
+ # It does not duplicate any other values
12
11
  #
13
- # @private
14
- class EnumDeepDup
12
+ class EnumDeepDup # :nodoc:
15
13
  class << self
16
- #
17
- # Deeply duplicate provided Array or Hash data
18
- # It does not duplicate any non-Array and non-Hash values
19
- #
20
- # @param data [Hash, Array] Data to duplicate
21
- #
22
- # @return [Hash, Array] Duplicated data
23
- #
14
+ # Deeply duplicate provided Array, Hash or String data
15
+ # It does not duplicate any other values
24
16
  def call(data)
25
17
  case data
26
18
  when Hash
@@ -30,9 +22,11 @@ class Serega
30
22
  when Array
31
23
  data = data.dup
32
24
  dup_array_values(data)
25
+ when String
26
+ data.dup
27
+ else
28
+ data
33
29
  end
34
-
35
- data
36
30
  end
37
31
 
38
32
  private
@@ -4,21 +4,13 @@ class Serega
4
4
  #
5
5
  # Utilities
6
6
  #
7
- # @private
8
- module SeregaUtils
7
+ module SeregaUtils # :nodoc:
9
8
  #
10
- # Utility to freeze nested hashes and arrays
9
+ # Utility to freeze nested hashes, arrays and strings
11
10
  #
12
- # @private
13
- class EnumDeepFreeze
11
+ class EnumDeepFreeze # :nodoc:
14
12
  class << self
15
- #
16
- # Freezes nested hashes and arrays
17
- #
18
- # @param data[Hash, Array] data to freeze
19
- #
20
- # @return [Hash, Array] same deeply frozen data
21
- #
13
+ # Freezes nested hashes and arrays, replaces strings with frozen copies
22
14
  def call(data)
23
15
  case data
24
16
  when Hash
@@ -27,9 +19,11 @@ class Serega
27
19
  when Array
28
20
  data.map! { |value| call(value) }
29
21
  data.freeze
22
+ when String
23
+ -data
24
+ else
25
+ data
30
26
  end
31
-
32
- data
33
27
  end
34
28
  end
35
29
  end
@@ -4,31 +4,22 @@ class Serega
4
4
  #
5
5
  # Utilities
6
6
  #
7
- # @private
8
- module SeregaUtils
7
+ module SeregaUtils # :nodoc:
9
8
  #
10
9
  # Utility to make method arguments signature
11
10
  #
12
- # @private
13
- class MethodSignature
11
+ class MethodSignature # :nodoc:
14
12
  SYMBOL_TO_PROC_SIGNATURE_RUBY2 = [[:rest]]
15
13
  SYMBOL_TO_PROC_SIGNATURE_RUBY3 = [[:req], [:rest]]
16
14
  private_constant :SYMBOL_TO_PROC_SIGNATURE_RUBY2
17
15
  private_constant :SYMBOL_TO_PROC_SIGNATURE_RUBY3
18
16
 
19
17
  class << self
20
- #
21
- # Generates method arguments signature
22
- #
23
- # @param callable [#call] callable object
24
- # @param pos_limit [Integer] Max count of positional parameters
25
- # @param keyword_args [Array<Symbol>] List of accepted keyword argument names
26
- #
27
- # @return [String] Method signature which consist of number of positional parameters and
28
- # keyword parameter names joined with undescrore.
29
- #
18
+ # Generates method arguments signature: the count of positional
19
+ # parameters and the keyword parameter names, joined with underscores,
20
+ # like "1_ctx"
30
21
  def call(callable, pos_limit:, keyword_args: [])
31
- params = callable.is_a?(Proc) ? callable.parameters : callable.method(:call).parameters
22
+ params = (callable.is_a?(Proc) || callable.is_a?(Method)) ? callable.parameters : callable.method(:call).parameters
32
23
 
33
24
  # Procs (but not lambdas) can accept all provided parameters
34
25
  return full_signature(pos_limit, keyword_args) if params.empty? && callable.is_a?(Proc) && !callable.lambda?
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ module SeregaUtils # :nodoc:
5
+ #
6
+ # Parses fields listed in one String, with nested fields in parentheses
7
+ #
8
+ class ParseStringModifiers # :nodoc:
9
+ SEPARATOR = /[,()]/
10
+ COMMA = ",".ord
11
+ LPAREN = "(".ord
12
+ private_constant :SEPARATOR, :COMMA, :LPAREN
13
+
14
+ class << self
15
+ # Parses string modifiers
16
+ #
17
+ # parse("user") => { user: {} }
18
+ # parse("user(id)") => { user: { id: {} } }
19
+ # parse("user(id,name)") => { user: { id: {}, name: {} } }
20
+ # parse("user,comments") => { user: {}, comments: {} }
21
+ # parse("user(comments(text))") => { user: { comments: { text: {} } } }
22
+ def parse(fields)
23
+ result = {}
24
+ storage = result
25
+ parent_storages = nil
26
+ start = 0
27
+
28
+ while (index = fields.byteindex(SEPARATOR, start))
29
+ name = extract_name(fields, start, index)
30
+ separator = fields.getbyte(index)
31
+
32
+ if separator == COMMA
33
+ storage[name] = FROZEN_EMPTY_HASH if name
34
+ elsif separator == LPAREN
35
+ if name
36
+ (parent_storages ||= []) << storage
37
+ storage = storage[name] = {}
38
+ end
39
+ else
40
+ storage[name] = FROZEN_EMPTY_HASH if name
41
+ storage = parent_storages&.pop || result
42
+ end
43
+
44
+ start = index + 1
45
+ end
46
+
47
+ name = extract_name(fields, start, fields.bytesize)
48
+ storage[name] = FROZEN_EMPTY_HASH if name
49
+
50
+ result
51
+ end
52
+
53
+ private
54
+
55
+ def extract_name(fields, start, finish)
56
+ name = fields.byteslice(start, finish - start)
57
+ name.strip!
58
+ name.empty? ? nil : name.to_sym
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ #
5
+ # Utilities
6
+ #
7
+ module SeregaUtils # :nodoc:
8
+ #
9
+ # Values stored in the current Ractor by key
10
+ #
11
+ class RactorLocal # :nodoc:
12
+ class << self
13
+ # Returns the key of the owner value with the name
14
+ def key(owner, name)
15
+ :"serega_#{name}_#{owner.object_id}"
16
+ end
17
+
18
+ # :nocov:
19
+ if defined?(Ractor.[])
20
+ # Returns the value of the key in the current Ractor, stores the
21
+ # block result when there is none
22
+ def fetch(key)
23
+ Ractor[key] ||= yield
24
+ end
25
+ else
26
+ # Returns the value of the key in the current Ractor, stores the
27
+ # block result when there is none
28
+ def fetch(key)
29
+ Ractor.current[key] ||= yield
30
+ end
31
+ end
32
+ # :nocov:
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,29 +1,69 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Serega
4
- # @private
5
- module SeregaUtils
4
+ module SeregaUtils # :nodoc:
6
5
  #
7
6
  # Reraises an error, adding which attribute and serializer were being
8
- # serialized when it happened. Shared by the synchronous serialization walk
9
- # and the batch attach phase so the message stays identical for every
10
- # attribute, whether its value is resolved inline or during batch loading.
7
+ # serialized when it happened, and where the attribute is defined. Value
8
+ # reads, preloads, batch loaders and attribute conditions use it.
11
9
  #
12
- # @private
13
- module SerializedAttributeError
14
- module_function
15
-
16
- #
17
- # @param error [Exception] Original error
18
- # @param point [SeregaPlanPoint] Plan point being serialized
19
- #
20
- # @return [void]
21
- #
22
- def call(error, point)
23
- raise error.exception(<<~MESSAGE.strip)
24
- #{error.message}
25
- (when serializing '#{point.name}' attribute in #{point.class.serializer_class})
26
- MESSAGE
10
+ module SerializedAttributeError # :nodoc:
11
+ # File name of the generated code in backtraces
12
+ GENERATED_CODE_FILE = "(serega generated code)"
13
+
14
+ class << self
15
+ # Reraises an error raised while a value is read, preloaded or batch
16
+ # loaded. An error raised in the generated code gets a backtrace line at
17
+ # the attribute, above the line of the generated code:
18
+ #
19
+ # app/serializers/user_serializer.rb:3:in 'attribute :full_name of UserSerializer'
20
+ # (serega generated code):20:in 'call'
21
+ def call(error, point)
22
+ location = point.attribute.location
23
+ serializer_class = point.plan.serializer_class
24
+ defined_at = location ? ", #{location}" : ""
25
+
26
+ exception = error.exception(<<~MESSAGE.strip)
27
+ #{error.message}
28
+ (when serializing the '#{point.name}' attribute in #{serializer_class}#{defined_at})
29
+ MESSAGE
30
+ add_attribute_line(exception, "#{location}:in 'attribute :#{point.name} of #{serializer_class}'") if location
31
+ raise exception
32
+ end
33
+
34
+ # Reraises an error raised by an :if, :unless, :if_value or
35
+ # :unless_value condition
36
+ def condition(error, attribute, condition_name)
37
+ location = attribute.location
38
+ defined_at = location ? ", #{location}" : ""
39
+
40
+ raise error.exception(<<~MESSAGE.strip)
41
+ #{error.message}
42
+ (when checking the :#{condition_name} condition of the '#{attribute.name}' attribute in #{attribute.serializer_class}#{defined_at})
43
+ MESSAGE
44
+ end
45
+
46
+ private
47
+
48
+ # Puts the line above the line of the generated code that called this
49
+ # module. The backtrace and the call stack share the outer lines, up
50
+ # to that line: the backtrace has the line of the read there, the
51
+ # call stack the line of the rescue.
52
+ def add_attribute_line(exception, line)
53
+ backtrace = exception.backtrace
54
+ return unless backtrace
55
+
56
+ index = backtrace.size - shared_outer_lines_count(backtrace, caller(2)) - 1
57
+ return if index.negative? || !backtrace[index].start_with?(GENERATED_CODE_FILE)
58
+
59
+ exception.set_backtrace(backtrace.dup.insert(index, line))
60
+ end
61
+
62
+ def shared_outer_lines_count(backtrace, stack)
63
+ count = 0
64
+ count += 1 while count < backtrace.size && count < stack.size && backtrace[-1 - count] == stack[-1 - count]
65
+ count
66
+ end
27
67
  end
28
68
  end
29
69
  end
@@ -1,20 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Serega
4
- # @private
5
- module SeregaUtils
4
+ module SeregaUtils # :nodoc:
6
5
  #
7
6
  # Utility to transform almost anything to Hash
8
7
  #
9
- # @private
10
- class ToHash
8
+ class ToHash # :nodoc:
11
9
  class << self
12
- #
13
10
  # Constructs deep hashes from provided data
14
11
  #
15
- # @param value [Array, Hash, String, Symbol, NilClass, FalseClass, TrueClass] Value to transform
16
- #
17
- # @example
18
12
  # Serega::SeregaUtils::ToHash.(nil) # => {}
19
13
  # Serega::SeregaUtils::ToHash.(true) # => {}
20
14
  # Serega::SeregaUtils::ToHash.(false) # => {}
@@ -24,16 +18,13 @@ class Serega
24
18
  # Serega::SeregaUtils::ToHash.({ foo: nil, bar: true }) # => {:foo=>{}, :bar=>{}}
25
19
  # Serega::SeregaUtils::ToHash.({ foo: :bar }) # => {:foo=>{:bar=>{}}}
26
20
  # Serega::SeregaUtils::ToHash.({ foo: [:bar] }) # => {:foo=>{:bar=>{}}}
27
- #
28
- # @return [Hash] Transformed data
29
- #
30
21
  def call(value)
31
22
  case value
32
23
  when Array then array_to_hash(value)
33
24
  when Hash then hash_to_hash(value)
34
- when NilClass, FalseClass, TrueClass then nil_to_hash(value)
35
- when String then string_to_hash(value)
36
- when Symbol then symbol_to_hash(value)
25
+ when NilClass, FalseClass, TrueClass then FROZEN_EMPTY_HASH
26
+ when String then {value.to_sym => FROZEN_EMPTY_HASH}
27
+ when Symbol then {value => FROZEN_EMPTY_HASH}
37
28
  else raise SeregaError, "Can't convert #{value.class} class object to hash"
38
29
  end
39
30
  end
@@ -63,18 +54,6 @@ class Serega
63
54
  end
64
55
  res
65
56
  end
66
-
67
- def nil_to_hash(_value)
68
- FROZEN_EMPTY_HASH
69
- end
70
-
71
- def string_to_hash(value)
72
- {value.to_sym => FROZEN_EMPTY_HASH}
73
- end
74
-
75
- def symbol_to_hash(value)
76
- {value => FROZEN_EMPTY_HASH}
77
- end
78
57
  end
79
58
  end
80
59
  end
@@ -1,18 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Serega
4
- # @private
5
- module SeregaValidations
4
+ module SeregaValidations # :nodoc:
6
5
  #
7
6
  # Attribute parameters validators
8
7
  #
9
- # @private
10
- module Attribute
8
+ module Attribute # :nodoc:
11
9
  #
12
10
  # Attribute `block` parameter validator
13
11
  #
14
- # @private
15
- class CheckBlock
12
+ class CheckBlock # :nodoc:
16
13
  # Explains the changed attribute block behavior. Shown when the block
17
14
  # looks like an old-style value block — it accepts parameters or
18
15
  # defines no attributes.
@@ -23,25 +20,16 @@ class Serega
23
20
  " use the `value: <callable>` option instead."
24
21
 
25
22
  class << self
26
- #
27
23
  # Checks block parameter provided with attribute.
28
24
  #
29
25
  # The block defines attributes of a nested anonymous serializer, so
30
26
  # it is executed in the context of that serializer and must accept
31
27
  # no parameters.
32
28
  #
33
- # @example
34
29
  # attribute :statistics, method: :itself do
35
30
  # attribute :likes_count
36
31
  # attribute :comments_count
37
32
  # end
38
- #
39
- # @param block [Proc] Block that defines nested serializer attributes
40
- #
41
- # @raise [SeregaError] SeregaError that block has invalid arguments
42
- #
43
- # @return [void]
44
- #
45
33
  def call(block)
46
34
  return unless block
47
35
 
@@ -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