serega 0.40.0 → 0.41.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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +21 -0
  3. data/README.md +204 -108
  4. data/VERSION +1 -1
  5. data/lib/serega/attribute.rb +2 -0
  6. data/lib/serega/attribute_normalizer.rb +2 -0
  7. data/lib/serega/attribute_value_resolvers/batch.rb +3 -0
  8. data/lib/serega/attribute_value_resolvers/const.rb +3 -0
  9. data/lib/serega/attribute_value_resolvers/delegate.rb +4 -0
  10. data/lib/serega/attribute_value_resolvers/hash_access.rb +6 -0
  11. data/lib/serega/attribute_value_resolvers/keyword.rb +3 -0
  12. data/lib/serega/data_builder.rb +2 -0
  13. data/lib/serega/engine/level.rb +2 -0
  14. data/lib/serega/engine/level_queue.rb +2 -0
  15. data/lib/serega/engine/loader.rb +3 -0
  16. data/lib/serega/helpers/serializer_class_helper.rb +2 -0
  17. data/lib/serega/object_serializer.rb +2 -0
  18. data/lib/serega/plan.rb +3 -0
  19. data/lib/serega/plan_point.rb +2 -0
  20. data/lib/serega/plugins/activerecord_preloads/activerecord_preloads.rb +22 -16
  21. data/lib/serega/plugins/activerecord_preloads/lib/preloader.rb +6 -0
  22. data/lib/serega/plugins/camel_case/camel_case.rb +13 -13
  23. data/lib/serega/plugins/context_metadata/context_metadata.rb +8 -1
  24. data/lib/serega/plugins/depth_limit/depth_limit.rb +15 -12
  25. data/lib/serega/plugins/explicit_many_option/explicit_many_option.rb +12 -10
  26. data/lib/serega/plugins/explicit_many_option/validations/check_opt_many.rb +1 -0
  27. data/lib/serega/plugins/formatters/formatters.rb +18 -10
  28. data/lib/serega/plugins/if/if.rb +29 -32
  29. data/lib/serega/plugins/if/validations/check_opt_if.rb +1 -0
  30. data/lib/serega/plugins/if/validations/check_opt_if_value.rb +1 -0
  31. data/lib/serega/plugins/if/validations/check_opt_unless.rb +1 -0
  32. data/lib/serega/plugins/if/validations/check_opt_unless_value.rb +1 -0
  33. data/lib/serega/plugins/metadata/meta_attribute.rb +2 -0
  34. data/lib/serega/plugins/metadata/metadata.rb +14 -12
  35. data/lib/serega/plugins/metadata/validations/check_block.rb +1 -0
  36. data/lib/serega/plugins/metadata/validations/check_opt_const.rb +1 -0
  37. data/lib/serega/plugins/metadata/validations/check_opt_hide_empty.rb +1 -0
  38. data/lib/serega/plugins/metadata/validations/check_opt_hide_nil.rb +1 -0
  39. data/lib/serega/plugins/metadata/validations/check_opt_value.rb +1 -0
  40. data/lib/serega/plugins/metadata/validations/check_opts.rb +1 -0
  41. data/lib/serega/plugins/metadata/validations/check_path.rb +1 -0
  42. data/lib/serega/plugins/presenter/presenter.rb +10 -7
  43. data/lib/serega/plugins/root/root.rb +12 -6
  44. data/lib/serega/plugins/string_modifiers/parse_string_modifiers.rb +1 -0
  45. data/lib/serega/plugins/string_modifiers/string_modifiers.rb +21 -0
  46. data/lib/serega/plugins.rb +2 -0
  47. data/lib/serega/utils/collection_detector.rb +2 -0
  48. data/lib/serega/utils/enum_deep_dup.rb +2 -0
  49. data/lib/serega/utils/enum_deep_freeze.rb +2 -0
  50. data/lib/serega/utils/method_signature.rb +2 -0
  51. data/lib/serega/utils/serialized_attribute_error.rb +2 -0
  52. data/lib/serega/utils/symbol_name.rb +2 -0
  53. data/lib/serega/utils/to_hash.rb +2 -0
  54. data/lib/serega/validations/attribute/check_block.rb +3 -0
  55. data/lib/serega/validations/attribute/check_name.rb +3 -0
  56. data/lib/serega/validations/attribute/check_opt_base_serializer.rb +3 -0
  57. data/lib/serega/validations/attribute/check_opt_batch.rb +3 -0
  58. data/lib/serega/validations/attribute/check_opt_const.rb +3 -0
  59. data/lib/serega/validations/attribute/check_opt_delegate.rb +3 -0
  60. data/lib/serega/validations/attribute/check_opt_hash_access.rb +3 -0
  61. data/lib/serega/validations/attribute/check_opt_hide.rb +3 -0
  62. data/lib/serega/validations/attribute/check_opt_many.rb +3 -0
  63. data/lib/serega/validations/attribute/check_opt_method.rb +3 -0
  64. data/lib/serega/validations/attribute/check_opt_preload.rb +3 -0
  65. data/lib/serega/validations/attribute/check_opt_serializer.rb +3 -0
  66. data/lib/serega/validations/attribute/check_opt_value.rb +3 -0
  67. data/lib/serega/validations/check_attribute_params.rb +3 -0
  68. data/lib/serega/validations/check_batch_loader_params.rb +3 -0
  69. data/lib/serega/validations/check_initiate_params.rb +3 -0
  70. data/lib/serega/validations/check_serialize_params.rb +3 -0
  71. data/lib/serega/validations/initiate/check_modifiers.rb +3 -0
  72. data/lib/serega/validations/utils/check_allowed_keys.rb +3 -0
  73. data/lib/serega/validations/utils/check_opt_is_bool.rb +3 -0
  74. data/lib/serega/validations/utils/check_opt_is_hash.rb +3 -0
  75. data/lib/serega/validations/utils/check_opt_is_string_or_symbol.rb +3 -0
  76. data/lib/serega.rb +95 -1
  77. metadata +13 -16
@@ -5,8 +5,10 @@ class Serega
5
5
  # Builds Data objects from serialized hashes.
6
6
  # Used by `#to_data` / `.to_data`.
7
7
  #
8
+ # @private
8
9
  class SeregaDataBuilder
9
10
  # SeregaDataBuilder class methods
11
+ # @private
10
12
  module SeregaDataBuilderClassMethods
11
13
  #
12
14
  # Converts serialized Hash/Array result into a tree of Ruby Data objects
@@ -4,6 +4,7 @@ class Serega
4
4
  #
5
5
  # Batch feature main module
6
6
  #
7
+ # @private
7
8
  module SeregaEngine
8
9
  #
9
10
  # One serialization level: all objects serialized under a single plan and the
@@ -12,6 +13,7 @@ class Serega
12
13
  # or preload runs once over the whole set. A deeper level (its own plan) loads
13
14
  # separately.
14
15
  #
16
+ # @private
15
17
  class Level
16
18
  # @param serializer [SeregaObjectSerializer] serializer that resolves this level
17
19
  def initialize(serializer)
@@ -4,6 +4,7 @@ class Serega
4
4
  #
5
5
  # Batch feature main module
6
6
  #
7
+ # @private
7
8
  module SeregaEngine
8
9
  #
9
10
  # Level-order queue of serialization levels for one serialization run.
@@ -15,6 +16,7 @@ class Serega
15
16
  # Processing level-by-level lets a named batch loader and preloads run once per
16
17
  # level over all of its objects.
17
18
  #
19
+ # @private
18
20
  class LevelQueue
19
21
  def initialize
20
22
  @levels = []
@@ -4,14 +4,17 @@ class Serega
4
4
  #
5
5
  # Batch feature main module
6
6
  #
7
+ # @private
7
8
  module SeregaEngine
8
9
  #
9
10
  # Batch loader
10
11
  #
12
+ # @private
11
13
  class Loader
12
14
  #
13
15
  # BatchLoader instance methods
14
16
  #
17
+ # @private
15
18
  module InstanceMethods
16
19
  # BatchLoader initial params
17
20
  # @return [Hash] BatchLoader initial params
@@ -4,10 +4,12 @@ class Serega
4
4
  #
5
5
  # Helpers
6
6
  #
7
+ # @private
7
8
  module SeregaHelpers
8
9
  #
9
10
  # Stores link to current serializer class
10
11
  #
12
+ # @private
11
13
  module SerializerClassHelper
12
14
  # Shows serializer class current class is namespaced under
13
15
  # @return [Class<Serega>] Serializer class that current class is namespaced under.
@@ -9,10 +9,12 @@ class Serega
9
9
  # which resolves every attribute for every object and enqueues child levels for
10
10
  # relations.
11
11
  #
12
+ # @private
12
13
  class SeregaObjectSerializer
13
14
  #
14
15
  # SeregaObjectSerializer instance methods
15
16
  #
17
+ # @private
16
18
  module InstanceMethods
17
19
  attr_reader :context, :plan, :many, :opts, :level_queue
18
20
 
data/lib/serega/plan.rb CHANGED
@@ -5,10 +5,12 @@ class Serega
5
5
  # Constructs plan - list of serialized attributes.
6
6
  # We will traverse this plan to construct serialized response.
7
7
  #
8
+ # @private
8
9
  class SeregaPlan
9
10
  #
10
11
  # SeregaPlan class methods
11
12
  #
13
+ # @private
12
14
  module ClassMethods
13
15
  #
14
16
  # Constructs plan of attributes that should be serialized.
@@ -68,6 +70,7 @@ class Serega
68
70
  #
69
71
  # SeregaPlan instance methods
70
72
  #
73
+ # @private
71
74
  module InstanceMethods
72
75
  # Parent plan point
73
76
  # @return [SeregaPlanPoint, nil]
@@ -4,10 +4,12 @@ class Serega
4
4
  #
5
5
  # Combines attribute and nested attributes
6
6
  #
7
+ # @private
7
8
  class SeregaPlanPoint
8
9
  #
9
10
  # SeregaPlanPoint instance methods
10
11
  #
12
+ # @private
11
13
  module InstanceMethods
12
14
  # Link to current plan this point belongs to
13
15
  # @return [SeregaAttribute] Current plan
@@ -12,38 +12,40 @@ class Serega
12
12
  #
13
13
  # @example
14
14
  # class AppSerializer < Serega
15
- # config.auto_preload_attributes_with_delegate = true
16
- # config.auto_preload_attributes_with_serializer = true
17
- # config.hide_by_default = [:preload]
18
- #
15
+ # config.auto_preload = true
19
16
  # plugin :activerecord_preloads
20
17
  # end
21
18
  #
22
- # class UserSerializer < AppSerializer
19
+ # class AlbumSerializer < AppSerializer
23
20
  # # no preloads
24
- # attribute :username
25
- #
26
- # # preloads `:user_stats` as auto_preload_attributes_with_delegate option is true
27
- # attribute :comments_count, delegate: { to: :user_stats }
21
+ # attribute :title
28
22
  #
29
- # # preloads `:albums` as auto_preload_attributes_with_serializer option is true
30
- # attribute :albums, serializer: AlbumSerializer, hide: false
23
+ # # preloads :downloads, as manually specified
24
+ # attribute :downloads_count, preload: :downloads, value: proc { |album| album.downloads.count }
31
25
  # end
32
26
  #
33
- # class AlbumSerializer < AppSerializer
27
+ # class UserSerializer < AppSerializer
34
28
  # # no preloads
35
- # attribute :title
29
+ # attribute :username
36
30
  #
37
- # # preloads :downloads_count as manually specified
38
- # attribute :downloads_count, preload: :downloads, value: proc { |album| album.downloads.count }
31
+ # # preloads :user_stats, as auto_preload is enabled for :delegate attributes
32
+ # attribute :comments_count, delegate: { to: :user_stats }
33
+ #
34
+ # # preloads :albums, as auto_preload is enabled for :serializer attributes
35
+ # attribute :albums, serializer: AlbumSerializer
39
36
  # end
40
37
  #
41
- # UserSerializer.to_h(user)
38
+ # UserSerializer.to_h(users)
39
+ # # 1 query to load :user_stats for all users
40
+ # # + 1 query to load :albums for all users
41
+ # # + 1 query to load :downloads for all albums
42
+ # # = 3 queries total, regardless of how many users/albums are serialized
42
43
  #
43
44
  module ActiverecordPreloads
44
45
  #
45
46
  # @return [Symbol] Plugin name
46
47
  #
48
+ # @private
47
49
  def self.plugin_name
48
50
  :activerecord_preloads
49
51
  end
@@ -55,6 +57,7 @@ class Serega
55
57
  #
56
58
  # @return [void]
57
59
  #
60
+ # @private
58
61
  def self.before_load_plugin(serializer_class, **opts)
59
62
  opts.each_key do |key|
60
63
  raise SeregaError, "Plugin #{plugin_name.inspect} does not accept the #{key.inspect} option. No options are allowed"
@@ -69,6 +72,7 @@ class Serega
69
72
  #
70
73
  # @return [void]
71
74
  #
75
+ # @private
72
76
  def self.load_plugin(serializer_class, **_opts)
73
77
  require_relative "lib/preloader"
74
78
  end
@@ -81,6 +85,7 @@ class Serega
81
85
  #
82
86
  # @return [void]
83
87
  #
88
+ # @private
84
89
  def self.after_load_plugin(serializer_class, **_opts)
85
90
  serializer_class.preload_with do |objects, preloads|
86
91
  Preloader.preload(ActiverecordPreloads.records(serializer_class, objects), preloads)
@@ -98,6 +103,7 @@ class Serega
98
103
  #
99
104
  # @return [Array] the underlying records
100
105
  #
106
+ # @private
101
107
  def self.records(serializer_class, objects)
102
108
  return objects unless serializer_class.plugin_used?(:presenter)
103
109
  return objects unless serializer_class.custom_presenter?
@@ -4,6 +4,7 @@ class Serega
4
4
  module SeregaPlugins
5
5
  module ActiverecordPreloads
6
6
  # Handles preloads for different types of initial records
7
+ # @private
7
8
  class Preloader
8
9
  class << self
9
10
  # Preloads associations to records
@@ -37,6 +38,7 @@ class Serega
37
38
  end
38
39
 
39
40
  # Associations loader for prepared records
41
+ # @private
40
42
  class Loader
41
43
  # :nocov: We can check only one version of activerecord
42
44
 
@@ -58,6 +60,7 @@ class Serega
58
60
  end
59
61
 
60
62
  # Preloader adapter for ActiveRecord object
63
+ # @private
61
64
  class ActiverecordObject
62
65
  class << self
63
66
  #
@@ -84,6 +87,7 @@ class Serega
84
87
  end
85
88
 
86
89
  # Preloader adapter for ActiveRecord::Relation
90
+ # @private
87
91
  class ActiverecordRelation
88
92
  class << self
89
93
  #
@@ -111,6 +115,7 @@ class Serega
111
115
  end
112
116
 
113
117
  # Preloader adapter for Array of ActiveRecord objects
118
+ # @private
114
119
  class ActiverecordArray
115
120
  class << self
116
121
  #
@@ -146,6 +151,7 @@ class Serega
146
151
  end
147
152
 
148
153
  # Preloader adapter for Enumerator with ActiveRecord objects
154
+ # @private
149
155
  class ActiverecordEnumerator
150
156
  class << self
151
157
  #
@@ -5,21 +5,14 @@ class Serega
5
5
  #
6
6
  # Plugin :camel_case
7
7
  #
8
- # By default when we add attribute like `attribute :first_name` this means:
9
- # - adding a `:first_name` key to resulted hash
10
- # - adding a `#first_name` method call result as value
8
+ # CamelCases every attribute name automatically, replacing `_x` with `X`
9
+ # throughout the string. Runs once, when the attribute is defined, not on
10
+ # every serialization.
11
11
  #
12
- # But its often desired to response with *camelCased* keys.
13
- # Earlier this can be achieved by specifying attribute name and method directly
14
- # for each attribute: `attribute :firstName, method: first_name`
12
+ # Provide a custom transformation with
13
+ # `plugin :camel_case, transform: ->(name) { name.camelize }`.
15
14
  #
16
- # Now this plugin transforms all attribute names automatically.
17
- # We use simple regular expression to replace `_x` to `X` for the whole string.
18
- # You can provide your own callable transformation when defining plugin,
19
- # for example `plugin :camel_case, transform: ->(name) { name.camelize }`
20
- #
21
- # For any attribute camelCase-behavior can be skipped when
22
- # `camel_case: false` attribute option provided.
15
+ # Skip camelCase for a single attribute with `camel_case: false`.
23
16
  #
24
17
  # @example Define plugin
25
18
  # class AppSerializer < Serega
@@ -44,6 +37,7 @@ class Serega
44
37
  }
45
38
 
46
39
  # @return [Symbol] Plugin name
40
+ # @private
47
41
  def self.plugin_name
48
42
  :camel_case
49
43
  end
@@ -55,6 +49,7 @@ class Serega
55
49
  #
56
50
  # @return [void]
57
51
  #
52
+ # @private
58
53
  def self.before_load_plugin(serializer_class, **opts)
59
54
  allowed_keys = %i[transform]
60
55
  opts.each_key do |key|
@@ -74,6 +69,7 @@ class Serega
74
69
  #
75
70
  # @return [void]
76
71
  #
72
+ # @private
77
73
  def self.load_plugin(serializer_class, **_opts)
78
74
  serializer_class::SeregaConfig.include(ConfigInstanceMethods)
79
75
  serializer_class::SeregaAttributeNormalizer.include(AttributeNormalizerInstanceMethods)
@@ -88,6 +84,7 @@ class Serega
88
84
  #
89
85
  # @return [void]
90
86
  #
87
+ # @private
91
88
  def self.after_load_plugin(serializer_class, **opts)
92
89
  config = serializer_class.config
93
90
  config.opts[:camel_case] = {}
@@ -113,6 +110,7 @@ class Serega
113
110
  #
114
111
  # @see Serega::SeregaValidations::CheckAttributeParams
115
112
  #
113
+ # @private
116
114
  module CheckAttributeParamsInstanceMethods
117
115
  private
118
116
 
@@ -125,6 +123,7 @@ class Serega
125
123
  #
126
124
  # Validator for attribute :camel_case option
127
125
  #
126
+ # @private
128
127
  class CheckOptCamelCase
129
128
  class << self
130
129
  #
@@ -191,6 +190,7 @@ class Serega
191
190
  #
192
191
  # @see SeregaAttributeNormalizer::AttributeInstanceMethods
193
192
  #
193
+ # @private
194
194
  module AttributeNormalizerInstanceMethods
195
195
  private
196
196
 
@@ -7,7 +7,8 @@ class Serega
7
7
  #
8
8
  # Depends on: `:root` plugin, that must be loaded first
9
9
  #
10
- # Allows to specify metadata to be added to serialized response.
10
+ # Adds metadata supplied per serialization call (as opposed to `:metadata`,
11
+ # which is defined statically on the serializer).
11
12
  #
12
13
  # @example
13
14
  # class UserSerializer < Serega
@@ -23,6 +24,7 @@ class Serega
23
24
  DEFAULT_CONTEXT_METADATA_KEY = :meta
24
25
 
25
26
  # @return [Symbol] Plugin name
27
+ # @private
26
28
  def self.plugin_name
27
29
  :context_metadata
28
30
  end
@@ -34,6 +36,7 @@ class Serega
34
36
  #
35
37
  # @return [void]
36
38
  #
39
+ # @private
37
40
  def self.before_load_plugin(serializer_class, **opts)
38
41
  allowed_keys = %i[context_metadata_key]
39
42
  opts.each_key do |key|
@@ -57,6 +60,7 @@ class Serega
57
60
  #
58
61
  # @return [void]
59
62
  #
63
+ # @private
60
64
  def self.load_plugin(serializer_class, **_opts)
61
65
  serializer_class.include(InstanceMethods)
62
66
  serializer_class::SeregaConfig.include(ConfigInstanceMethods)
@@ -71,6 +75,7 @@ class Serega
71
75
  #
72
76
  # @return [void]
73
77
  #
78
+ # @private
74
79
  def self.after_load_plugin(serializer_class, **opts)
75
80
  config = serializer_class.config
76
81
  meta_key = opts[:context_metadata_key] || DEFAULT_CONTEXT_METADATA_KEY
@@ -127,6 +132,7 @@ class Serega
127
132
  #
128
133
  # @see Serega::SeregaValidations::CheckSerializeParams
129
134
  #
135
+ # @private
130
136
  module CheckSerializeParamsInstanceMethods
131
137
  private
132
138
 
@@ -143,6 +149,7 @@ class Serega
143
149
  #
144
150
  # @see Serega
145
151
  #
152
+ # @private
146
153
  module InstanceMethods
147
154
  private
148
155
 
@@ -5,25 +5,23 @@ class Serega
5
5
  #
6
6
  # Plugin :depth_limit
7
7
  #
8
- # Helps to secure from malicious queries that require to serialize too much
9
- # or from accidental serializing of objects with cyclic relations.
8
+ # Guards against malicious queries that serialize too much, or against
9
+ # accidentally serializing objects with cyclic relations.
10
10
  #
11
- # Depth limit is checked when constructing a serialization plan, that is when
12
- # `#new` method is called, ex: `SomeSerializer.new(with: params[:with])`.
13
- # It can be useful to instantiate serializer before any other business logic
14
- # to get possible errors earlier.
11
+ # Depth limit is checked when a serialization plan is built, i.e. when
12
+ # `#new` is called (`SomeSerializer.new(with: params[:with])`) — including
13
+ # internally by every class-level serialization method. Instantiating the
14
+ # serializer early surfaces depth errors sooner.
15
15
  #
16
- # Any class-level serialization methods also check depth limit as they also instantiate serializer.
16
+ # When the limit is exceeded, `Serega::DepthLimitError` is raised;
17
+ # details are available via `Serega::DepthLimitError#details`.
17
18
  #
18
- # When depth limit is exceeded `Serega::DepthLimitError` is raised.
19
- # Depth limit error details can be found in additional `Serega::DepthLimitError#details` method
20
- #
21
- # Limit can be checked or changed with next config options:
19
+ # Limit can be checked or changed with config options:
22
20
  #
23
21
  # - config.depth_limit.limit
24
22
  # - config.depth_limit.limit=
25
23
  #
26
- # There are no default limit, but it should be set when enabling plugin.
24
+ # There is no default limit it must be set when enabling the plugin.
27
25
  #
28
26
  # @example
29
27
  #
@@ -37,6 +35,7 @@ class Serega
37
35
  #
38
36
  module DepthLimit
39
37
  # @return [Symbol] Plugin name
38
+ # @private
40
39
  def self.plugin_name
41
40
  :depth_limit
42
41
  end
@@ -48,6 +47,7 @@ class Serega
48
47
  #
49
48
  # @return [void]
50
49
  #
50
+ # @private
51
51
  def self.before_load_plugin(serializer_class, **opts)
52
52
  allowed_keys = %i[limit]
53
53
  opts.each_key do |key|
@@ -67,6 +67,7 @@ class Serega
67
67
  #
68
68
  # @return [void]
69
69
  #
70
+ # @private
70
71
  def self.load_plugin(serializer_class, **_opts)
71
72
  serializer_class::SeregaPlan.include(PlanInstanceMethods)
72
73
  serializer_class::SeregaConfig.include(ConfigInstanceMethods)
@@ -80,6 +81,7 @@ class Serega
80
81
  #
81
82
  # @return [void]
82
83
  #
84
+ # @private
83
85
  def self.after_load_plugin(serializer_class, **opts)
84
86
  config = serializer_class.config
85
87
  limit = opts.fetch(:limit) { raise SeregaError, "Please provide :limit option. Example: `plugin :depth_limit, limit: 10`" }
@@ -137,6 +139,7 @@ class Serega
137
139
  #
138
140
  # @see SeregaPlan
139
141
  #
142
+ # @private
140
143
  module PlanInstanceMethods
141
144
  #
142
145
  # Initializes serialization plan
@@ -5,29 +5,29 @@ class Serega
5
5
  #
6
6
  # Plugin :explicit_many_option
7
7
  #
8
- # Plugin requires to add :many option when adding relationships
9
- # (relationships are attributes with the :serializer option or a block
10
- # defining a nested serializer)
11
- #
12
- # Adding this plugin makes it clearer to find if relationship returns array or single object
8
+ # Requires the `:many` option on every relationship attribute (an
9
+ # attribute with the `:serializer` option or a block defining a nested
10
+ # serializer), so it's always explicit whether it returns one object or many.
13
11
  #
14
12
  # @example
15
13
  # class BaseSerializer < Serega
16
14
  # plugin :explicit_many_option
17
- # end
18
- #
19
- # class UserSerializer < BaseSerializer
20
- # attribute :name
15
+ # config.base_serializer = self
21
16
  # end
22
17
  #
23
18
  # class PostSerializer < BaseSerializer
24
19
  # attribute :text
25
- # attribute :user, serializer: UserSerializer, many: false
20
+ #
21
+ # attribute :user, many: false do
22
+ # attribute :name
23
+ # end
24
+ #
26
25
  # attribute :comments, serializer: PostSerializer, many: true
27
26
  # end
28
27
  #
29
28
  module ExplicitManyOption
30
29
  # @return [Symbol] Plugin name
30
+ # @private
31
31
  def self.plugin_name
32
32
  :explicit_many_option
33
33
  end
@@ -40,6 +40,7 @@ class Serega
40
40
  #
41
41
  # @return [void]
42
42
  #
43
+ # @private
43
44
  def self.load_plugin(serializer_class, **_opts)
44
45
  require_relative "validations/check_opt_many"
45
46
 
@@ -51,6 +52,7 @@ class Serega
51
52
  #
52
53
  # @see Serega::SeregaValidations::CheckAttributeParams
53
54
  #
55
+ # @private
54
56
  module CheckAttributeParamsInstanceMethods
55
57
  private
56
58
 
@@ -6,6 +6,7 @@ class Serega
6
6
  #
7
7
  # Validator for attribute :many option
8
8
  #
9
+ # @private
9
10
  class CheckOptMany
10
11
  class << self
11
12
  #
@@ -5,20 +5,19 @@ class Serega
5
5
  #
6
6
  # Plugin :formatters
7
7
  #
8
- # Allows to define value formatters one time and apply them on any attributes.
8
+ # Defines named value formatters once and applies them to any attribute.
9
9
  #
10
- # Config option `config.formatters.add()` can be used to add formatters.
10
+ # Use `config.formatters.add()` to register formatters. The `:format`
11
+ # attribute option then accepts a formatter name or a callable directly.
11
12
  #
12
- # Attribute option `:format` now can be used with name of formatter or with callable instance.
13
- #
14
- # Formatters can accept up to 2 parameters (formatted object, context)
13
+ # Formatters receive up to 2 parameters: the value and the context.
15
14
  #
16
15
  # @example
17
16
  # class AppSerializer < Serega
18
17
  # plugin :formatters, formatters: {
19
- # iso8601: ->(value) { time.iso8601.round(6) },
18
+ # iso8601: ->(value) { value.iso8601 },
20
19
  # on_off: ->(value) { value ? 'ON' : 'OFF' },
21
- # money: ->(value) { value.round(2) }
20
+ # money: ->(value) { value.round(2) },
22
21
  # date: DateTypeFormatter # callable
23
22
  # }
24
23
  # end
@@ -26,24 +25,25 @@ class Serega
26
25
  # class UserSerializer < Serega
27
26
  # # Additionally we can add formatters via config in subclasses
28
27
  # config.formatters.add(
29
- # iso8601: ->(value) { time.iso8601.round(6) },
28
+ # iso8601: ->(value) { value.iso8601 },
30
29
  # on_off: ->(value) { value ? 'ON' : 'OFF' },
31
30
  # money: ->(value) { value.round(2) }
32
31
  # )
33
32
  #
34
33
  # # Using predefined formatter
35
34
  # attribute :commission, format: :money
36
- # attribute :is_logined, format: :on_off
35
+ # attribute :is_logged_in, format: :on_off
37
36
  # attribute :created_at, format: :iso8601
38
37
  # attribute :updated_at, format: :iso8601
39
38
  #
40
39
  # # Using `callable` formatter
41
- # attribute :score_percent, format: PercentFormmatter # callable class
40
+ # attribute :score_percent, format: PercentFormatter # callable class
42
41
  # attribute :score_percent, format: proc { |percent| "#{percent.round(2)}%" }
43
42
  # end
44
43
  #
45
44
  module Formatters
46
45
  # @return [Symbol] Plugin name
46
+ # @private
47
47
  def self.plugin_name
48
48
  :formatters
49
49
  end
@@ -55,6 +55,7 @@ class Serega
55
55
  #
56
56
  # @return [void]
57
57
  #
58
+ # @private
58
59
  def self.before_load_plugin(serializer_class, **opts)
59
60
  allowed_keys = %i[formatters]
60
61
  opts.each_key do |key|
@@ -74,6 +75,7 @@ class Serega
74
75
  #
75
76
  # @return [void]
76
77
  #
78
+ # @private
77
79
  def self.load_plugin(serializer_class, **_opts)
78
80
  serializer_class::SeregaConfig.include(ConfigInstanceMethods)
79
81
  serializer_class::SeregaAttributeNormalizer.include(AttributeNormalizerInstanceMethods)
@@ -89,6 +91,7 @@ class Serega
89
91
  #
90
92
  # @return [void]
91
93
  #
94
+ # @private
92
95
  def self.after_load_plugin(serializer_class, **opts)
93
96
  config = serializer_class.config
94
97
  config.opts[:formatters] = {}
@@ -141,6 +144,7 @@ class Serega
141
144
  #
142
145
  # @see Serega::SeregaValidations::CheckAttributeParams
143
146
  #
147
+ # @private
144
148
  module CheckAttributeParamsInstanceMethods
145
149
  private
146
150
 
@@ -156,6 +160,7 @@ class Serega
156
160
  #
157
161
  # @see SeregaAttributeNormalizer
158
162
  #
163
+ # @private
159
164
  module AttributeNormalizerInstanceMethods
160
165
  # Block or callable instance that will format attribute values
161
166
  # @return [Proc, #call, nil] Block or callable instance that will format attribute values
@@ -194,6 +199,7 @@ class Serega
194
199
  #
195
200
  # @see SeregaAttribute
196
201
  #
202
+ # @private
197
203
  module AttributeInstanceMethods
198
204
  #
199
205
  # Returns formatted attribute value
@@ -229,6 +235,7 @@ class Serega
229
235
  #
230
236
  # Validator for attribute :format option
231
237
  #
238
+ # @private
232
239
  class CheckOptFormat
233
240
  class << self
234
241
  #
@@ -265,6 +272,7 @@ class Serega
265
272
  #
266
273
  # Validator for formatters defined as config options or directly as attribute :format option
267
274
  #
275
+ # @private
268
276
  class CheckFormatter
269
277
  class << self
270
278
  #