serega 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/VERSION +1 -0
  3. data/lib/serega/attribute.rb +130 -0
  4. data/lib/serega/config.rb +48 -0
  5. data/lib/serega/convert.rb +45 -0
  6. data/lib/serega/convert_item.rb +37 -0
  7. data/lib/serega/helpers/serializer_class_helper.rb +11 -0
  8. data/lib/serega/map.rb +49 -0
  9. data/lib/serega/plugins/activerecord_preloads/activerecord_preloads.rb +61 -0
  10. data/lib/serega/plugins/activerecord_preloads/lib/preloader.rb +95 -0
  11. data/lib/serega/plugins/context_metadata/context_metadata.rb +74 -0
  12. data/lib/serega/plugins/formatters/formatters.rb +49 -0
  13. data/lib/serega/plugins/hide_nil/hide_nil.rb +80 -0
  14. data/lib/serega/plugins/metadata/meta_attribute.rb +74 -0
  15. data/lib/serega/plugins/metadata/metadata.rb +123 -0
  16. data/lib/serega/plugins/metadata/validations/check_block.rb +45 -0
  17. data/lib/serega/plugins/metadata/validations/check_opt_hide_empty.rb +31 -0
  18. data/lib/serega/plugins/metadata/validations/check_opt_hide_nil.rb +31 -0
  19. data/lib/serega/plugins/metadata/validations/check_opts.rb +41 -0
  20. data/lib/serega/plugins/metadata/validations/check_path.rb +53 -0
  21. data/lib/serega/plugins/preloads/lib/enum_deep_freeze.rb +17 -0
  22. data/lib/serega/plugins/preloads/lib/format_user_preloads.rb +53 -0
  23. data/lib/serega/plugins/preloads/lib/main_preload_path.rb +40 -0
  24. data/lib/serega/plugins/preloads/lib/preloads_constructor.rb +60 -0
  25. data/lib/serega/plugins/preloads/preloads.rb +100 -0
  26. data/lib/serega/plugins/preloads/validations/check_opt_preload_path.rb +38 -0
  27. data/lib/serega/plugins/presenter/presenter.rb +111 -0
  28. data/lib/serega/plugins/root/root.rb +65 -0
  29. data/lib/serega/plugins/string_modifiers/parse_string_modifiers.rb +64 -0
  30. data/lib/serega/plugins/string_modifiers/string_modifiers.rb +32 -0
  31. data/lib/serega/plugins/validate_modifiers/validate.rb +51 -0
  32. data/lib/serega/plugins/validate_modifiers/validate_modifiers.rb +44 -0
  33. data/lib/serega/plugins.rb +51 -0
  34. data/lib/serega/utils/as_json.rb +35 -0
  35. data/lib/serega/utils/enum_deep_dup.rb +43 -0
  36. data/lib/serega/utils/to_hash.rb +52 -0
  37. data/lib/serega/utils/to_json.rb +22 -0
  38. data/lib/serega/validations/attribute/check_block.rb +81 -0
  39. data/lib/serega/validations/attribute/check_name.rb +45 -0
  40. data/lib/serega/validations/attribute/check_opt_hide.rb +20 -0
  41. data/lib/serega/validations/attribute/check_opt_many.rb +20 -0
  42. data/lib/serega/validations/attribute/check_opt_method.rb +25 -0
  43. data/lib/serega/validations/attribute/check_opt_serializer.rb +36 -0
  44. data/lib/serega/validations/attribute/check_opts.rb +36 -0
  45. data/lib/serega/validations/check_allowed_keys.rb +13 -0
  46. data/lib/serega/validations/check_opt_is_bool.rb +14 -0
  47. data/lib/serega/validations/check_opt_is_hash.rb +14 -0
  48. data/lib/serega/version.rb +5 -0
  49. data/lib/serega.rb +265 -0
  50. metadata +94 -0
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ class Attribute
5
+ class CheckName
6
+ FORMAT_ONE_CHAR = /\A[a-zA-Z0-9]\z/
7
+ FORMAT_MANY_CHARS = /\A[a-zA-Z0-9][a-zA-Z0-9_-]*?[a-zA-Z0-9]\z/ # allow '-' and '_' in the middle
8
+
9
+ private_constant :FORMAT_ONE_CHAR, :FORMAT_MANY_CHARS
10
+
11
+ class << self
12
+ #
13
+ # Checks allowed characters.
14
+ # Globally allowed characters: "a-z", "A-Z", "0-9".
15
+ # Minus and low line "-", "_" also allowed except as the first or last character.
16
+ #
17
+ # @param name [String, Symbol] Attribute name
18
+ #
19
+ # @raise [Error] when name has invalid format
20
+ # @return [void]
21
+ #
22
+ def call(name)
23
+ name = name.to_s
24
+
25
+ valid =
26
+ case name.size
27
+ when 0 then false
28
+ when 1 then name.match?(FORMAT_ONE_CHAR)
29
+ else name.match?(FORMAT_MANY_CHARS)
30
+ end
31
+
32
+ return if valid
33
+
34
+ raise Error, message(name)
35
+ end
36
+
37
+ private
38
+
39
+ def message(name)
40
+ %(Invalid attribute name = #{name.inspect}. Globally allowed characters: "a-z", "A-Z", "0-9". Minus and low line "-", "_" also allowed except as the first or last character)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ class Attribute
5
+ class CheckOptHide
6
+ #
7
+ # Checks attribute :hide option
8
+ #
9
+ # @param opts [Hash] Attribute options
10
+ #
11
+ # @raise [Error] Error that option has invalid value
12
+ #
13
+ # @return [void]
14
+ #
15
+ def self.call(opts)
16
+ CheckOptIsBool.call(opts, :hide)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ class Attribute
5
+ class CheckOptMany
6
+ #
7
+ # Checks attribute :many option
8
+ #
9
+ # @param opts [Hash] Attribute options
10
+ #
11
+ # @raise [Error] Error that option has invalid value
12
+ #
13
+ # @return [void]
14
+ #
15
+ def self.call(opts)
16
+ CheckOptIsBool.call(opts, :many)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ class Attribute
5
+ class CheckOptMethod
6
+ #
7
+ # Checks attribute :method option
8
+ #
9
+ # @param opts [Hash] Attribute options
10
+ #
11
+ # @raise [Error] Error that option has invalid value
12
+ #
13
+ # @return [void]
14
+ #
15
+ def self.call(opts)
16
+ return unless opts.key?(:method)
17
+
18
+ value = opts[:method]
19
+ return if value.is_a?(String) || value.is_a?(Symbol)
20
+
21
+ raise Error, "Invalid option :method => #{value.inspect}. Must be a String or a Symbol"
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ class Attribute
5
+ class CheckOptSerializer
6
+ class << self
7
+ #
8
+ # Checks attribute :serializer option
9
+ #
10
+ # @param opts [Hash] Attribute options
11
+ #
12
+ # @raise [Error] Error that option has invalid value
13
+ #
14
+ # @return [void]
15
+ #
16
+ def call(opts)
17
+ return unless opts.key?(:serializer)
18
+
19
+ value = opts[:serializer]
20
+ return if valid_serializer?(value)
21
+
22
+ raise Error, "Invalid option :serializer => #{value.inspect}." \
23
+ " Can be a Serega subclass, a String or a Proc without arguments"
24
+ end
25
+
26
+ private
27
+
28
+ def valid_serializer?(value)
29
+ value.is_a?(String) ||
30
+ (value.is_a?(Proc) && (value.parameters.count == 0)) ||
31
+ (value.is_a?(Class) && (value < Serega))
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ class Attribute
5
+ class CheckOpts
6
+ module ClassMethods
7
+ #
8
+ # Validates attribute options
9
+ # Checks used options are allowed and then checks options values.
10
+ #
11
+ # @param opts [Hash] Attribute options
12
+ # @param attribute_keys [Array<Symbol>] Allowed options keys
13
+ #
14
+ # @raise [Error] when attribute has invalid options
15
+ #
16
+ # @return [void]
17
+ #
18
+ def call(opts, attribute_keys)
19
+ CheckAllowedKeys.call(opts, attribute_keys)
20
+ check_each_opt(opts)
21
+ end
22
+
23
+ private
24
+
25
+ def check_each_opt(opts)
26
+ CheckOptHide.call(opts)
27
+ CheckOptMethod.call(opts)
28
+ CheckOptMany.call(opts)
29
+ CheckOptSerializer.call(opts)
30
+ end
31
+ end
32
+
33
+ extend ClassMethods
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ class CheckAllowedKeys
5
+ def self.call(opts, allowed_keys)
6
+ opts.each_key do |key|
7
+ next if allowed_keys.include?(key)
8
+
9
+ raise Error, "Invalid option #{key.inspect}. Allowed options are: #{allowed_keys.map(&:inspect).join(", ")}"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ class CheckOptIsBool
5
+ def self.call(opts, key)
6
+ return unless opts.key?(key)
7
+
8
+ value = opts[key]
9
+ return if value.equal?(true) || value.equal?(false)
10
+
11
+ raise Error, "Invalid option #{key.inspect} => #{value.inspect}. Must have a boolean value"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ class CheckOptIsHash
5
+ def self.call(opts, key)
6
+ return unless opts.key?(key)
7
+
8
+ value = opts[key]
9
+ return if value.is_a?(Hash)
10
+
11
+ raise Error, "Invalid option #{key.inspect} => #{value.inspect}. Must have a Hash value"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ VERSION = File.read(File.join(File.dirname(__FILE__), "../../VERSION")).strip
5
+ end
data/lib/serega.rb ADDED
@@ -0,0 +1,265 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "serega/version"
4
+
5
+ # Parent class for your serializers
6
+ class Serega
7
+ # A generic exception Serega uses.
8
+ class Error < StandardError; end
9
+
10
+ # @return [Hash] frozen hash
11
+ FROZEN_EMPTY_HASH = {}.freeze
12
+
13
+ # @return [Array] frozen array
14
+ FROZEN_EMPTY_ARRAY = [].freeze
15
+ end
16
+
17
+ require_relative "serega/helpers/serializer_class_helper"
18
+ require_relative "serega/utils/enum_deep_dup"
19
+ require_relative "serega/utils/to_hash"
20
+ require_relative "serega/utils/to_json"
21
+ require_relative "serega/utils/as_json"
22
+
23
+ require_relative "serega/attribute"
24
+ require_relative "serega/validations/check_allowed_keys"
25
+ require_relative "serega/validations/check_opt_is_bool"
26
+ require_relative "serega/validations/check_opt_is_hash"
27
+ require_relative "serega/validations/attribute/check_block"
28
+ require_relative "serega/validations/attribute/check_name"
29
+ require_relative "serega/validations/attribute/check_opt_hide"
30
+ require_relative "serega/validations/attribute/check_opt_method"
31
+ require_relative "serega/validations/attribute/check_opt_many"
32
+ require_relative "serega/validations/attribute/check_opt_serializer"
33
+ require_relative "serega/validations/attribute/check_opts"
34
+
35
+ require_relative "serega/config"
36
+ require_relative "serega/convert"
37
+ require_relative "serega/convert_item"
38
+ require_relative "serega/map"
39
+ require_relative "serega/plugins"
40
+
41
+ class Serega
42
+ @config = Config.new(
43
+ {
44
+ plugins: [],
45
+ initiate_keys: %i[only with except],
46
+ attribute_keys: %i[key value serializer many hide],
47
+ serialize_keys: %i[context many],
48
+ max_cached_map_per_serializer_count: 50,
49
+ to_json: ->(data) { Utils::ToJSON.call(data) }
50
+ }
51
+ )
52
+
53
+ # Core serializer class methods
54
+ module ClassMethods
55
+ # @return [Config] current serializer config
56
+ attr_reader :config
57
+
58
+ private def inherited(subclass)
59
+ config_class = Class.new(self::Config)
60
+ config_class.serializer_class = subclass
61
+ subclass.const_set(:Config, config_class)
62
+ subclass.instance_variable_set(:@config, subclass::Config.new(config.opts))
63
+
64
+ attribute_class = Class.new(self::Attribute)
65
+ attribute_class.serializer_class = subclass
66
+ subclass.const_set(:Attribute, attribute_class)
67
+
68
+ map_class = Class.new(self::Map)
69
+ map_class.serializer_class = subclass
70
+ subclass.const_set(:Map, map_class)
71
+
72
+ convert_class = Class.new(self::Convert)
73
+ convert_class.serializer_class = subclass
74
+ subclass.const_set(:Convert, convert_class)
75
+
76
+ convert_item_class = Class.new(self::ConvertItem)
77
+ convert_item_class.serializer_class = subclass
78
+ subclass.const_set(:ConvertItem, convert_item_class)
79
+
80
+ # Assign same attributes
81
+ attributes.each_value do |attr|
82
+ subclass.attribute(attr.name, **attr.opts, &attr.block)
83
+ end
84
+
85
+ super
86
+ end
87
+
88
+ #
89
+ # Enables plugin for current serializer
90
+ #
91
+ # @param name [Symbol, Class<Module>] Plugin name or plugin module itself
92
+ # @param opts [Hash>] Plugin options
93
+ #
94
+ # @return [class<Module>] Loaded plugin module
95
+ #
96
+ def plugin(name, **opts)
97
+ raise Error, "This plugin is already loaded" if plugin_used?(name)
98
+
99
+ plugin = Plugins.find_plugin(name)
100
+
101
+ # We split loading of plugin to three parts - before_load, load, after_load:
102
+ #
103
+ # - **before_load_plugin** usually used to check requirements and to load additional plugins
104
+ # - **load_plugin** usually used to include plugin modules
105
+ # - **after_load_plugin** usually used to add config options
106
+ plugin.before_load_plugin(self, **opts) if plugin.respond_to?(:before_load_plugin)
107
+ plugin.load_plugin(self, **opts) if plugin.respond_to?(:load_plugin)
108
+ plugin.after_load_plugin(self, **opts) if plugin.respond_to?(:after_load_plugin)
109
+
110
+ # Store attached plugins, so we can check it is loaded later
111
+ config[:plugins] << (plugin.respond_to?(:plugin_name) ? plugin.plugin_name : plugin)
112
+
113
+ plugin
114
+ end
115
+
116
+ #
117
+ # Checks plugin is used
118
+ #
119
+ # @param name [Symbol, Class<Module>] Plugin name or plugin module itself
120
+ #
121
+ # @return [Boolean]
122
+ #
123
+ def plugin_used?(name)
124
+ plugin_name =
125
+ case name
126
+ when Module then name.respond_to?(:plugin_name) ? name.plugin_name : name
127
+ else name
128
+ end
129
+
130
+ config[:plugins].include?(plugin_name)
131
+ end
132
+
133
+ #
134
+ # Lists attributes
135
+ #
136
+ # @return [Hash] attributes list
137
+ #
138
+ def attributes
139
+ @attributes ||= {}
140
+ end
141
+
142
+ #
143
+ # Adds attribute
144
+ #
145
+ # @param name [Symbol] Attribute name. Attribute value will be found by executing `object.<name>`
146
+ # @param opts [Hash] Options to serialize attribute
147
+ # @param block [Proc] Custom block to find attribute value. Accepts object and context.
148
+ #
149
+ # @return [Serega::Attribute] Added attribute
150
+ #
151
+ def attribute(name, **opts, &block)
152
+ attribute = self::Attribute.new(name: name, opts: opts, block: block)
153
+ attributes[attribute.name] = attribute
154
+ end
155
+
156
+ #
157
+ # Adds attribute with forced :serializer option
158
+ #
159
+ # @param name [Symbol] Attribute name. Attribute value will be found by executing `object.<name>`
160
+ # @param serializer [Serega, Proc] Specifies nested serializer for relationship
161
+ # @param opts [Hash] Options for attribute serialization
162
+ # @param block [Proc] Custom block to find attribute value. Accepts object and context.
163
+ #
164
+ # @return [Serega::Attribute] Added attribute
165
+ #
166
+ def relation(name, serializer:, **opts, &block)
167
+ attribute(name, serializer: serializer, **opts, &block)
168
+ end
169
+
170
+ def to_h(object, opts = FROZEN_EMPTY_HASH)
171
+ initiate_keys = config[:initiate_keys]
172
+ new(opts.slice(*initiate_keys)).to_h(object, opts.except(*initiate_keys))
173
+ end
174
+
175
+ def to_json(object, opts = FROZEN_EMPTY_HASH)
176
+ initiate_keys = config[:initiate_keys]
177
+ new(opts.slice(*initiate_keys)).to_json(object, opts.except(*initiate_keys))
178
+ end
179
+
180
+ def as_json(object, opts = FROZEN_EMPTY_HASH)
181
+ initiate_keys = config[:initiate_keys]
182
+ new(opts.slice(*initiate_keys)).as_json(object, opts.except(*initiate_keys))
183
+ end
184
+ end
185
+
186
+ #
187
+ # Core serializer instance methods
188
+ #
189
+ module InstanceMethods
190
+ attr_reader :opts
191
+
192
+ #
193
+ # Instantiates new Serega class
194
+ #
195
+ # @param only [Array, Hash, String, Symbol] The only attributes to serialize
196
+ # @param except [Array, Hash, String, Symbol] Attributes to hide
197
+ # @param with [Array, Hash, String, Symbol] Attributes (usually hidden) to serialize additionally
198
+ #
199
+ def initialize(opts = FROZEN_EMPTY_HASH)
200
+ CheckAllowedKeys.call(opts, self.class.config[:initiate_keys])
201
+ opts = prepare_modifiers(opts) if opts && (opts != FROZEN_EMPTY_HASH)
202
+ @opts = opts
203
+ end
204
+
205
+ #
206
+ # Serializes provided object to hash
207
+ #
208
+ # @param object [Object] Serialized object
209
+ # @param opts [Hash] Serialization options, like :context and :many
210
+ #
211
+ # @return [Hash] Serialization result
212
+ #
213
+ def to_h(object, opts = {})
214
+ CheckAllowedKeys.call(opts, self.class.config[:serialize_keys])
215
+ CheckOptIsHash.call(opts, :context)
216
+ CheckOptIsBool.call(opts, :many)
217
+ opts[:context] ||= {}
218
+
219
+ self.class::Convert.call(object, **opts, map: map)
220
+ end
221
+
222
+ #
223
+ # Serializes provided object to json
224
+ #
225
+ # @param object [Object] Serialized object
226
+ #
227
+ # @return [Hash] Serialization result
228
+ #
229
+ def to_json(object, opts = FROZEN_EMPTY_HASH)
230
+ hash = to_h(object, opts)
231
+ self.class.config[:to_json].call(hash)
232
+ end
233
+
234
+ #
235
+ # Serializes provided object as json (uses only JSON-compatible types)
236
+ # When you later serialize/deserialize it from JSON you should receive
237
+ # equal object
238
+ #
239
+ # @param object [Object] Serialized object
240
+ #
241
+ # @return [Hash] Serialization result
242
+ #
243
+ def as_json(object, opts = FROZEN_EMPTY_HASH)
244
+ hash = to_h(object, opts)
245
+ Utils::AsJSON.call(hash, to_json: self.class.config[:to_json])
246
+ end
247
+
248
+ private
249
+
250
+ def map
251
+ @map ||= self.class::Map.call(opts)
252
+ end
253
+
254
+ def prepare_modifiers(opts)
255
+ {
256
+ only: Utils::ToHash.call(opts[:only]),
257
+ except: Utils::ToHash.call(opts[:except]),
258
+ with: Utils::ToHash.call(opts[:with])
259
+ }
260
+ end
261
+ end
262
+
263
+ extend ClassMethods
264
+ include InstanceMethods
265
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: serega
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrey Glushkov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-07-08 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ - aglushkov@shakuro.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - VERSION
21
+ - lib/serega.rb
22
+ - lib/serega/attribute.rb
23
+ - lib/serega/config.rb
24
+ - lib/serega/convert.rb
25
+ - lib/serega/convert_item.rb
26
+ - lib/serega/helpers/serializer_class_helper.rb
27
+ - lib/serega/map.rb
28
+ - lib/serega/plugins.rb
29
+ - lib/serega/plugins/activerecord_preloads/activerecord_preloads.rb
30
+ - lib/serega/plugins/activerecord_preloads/lib/preloader.rb
31
+ - lib/serega/plugins/context_metadata/context_metadata.rb
32
+ - lib/serega/plugins/formatters/formatters.rb
33
+ - lib/serega/plugins/hide_nil/hide_nil.rb
34
+ - lib/serega/plugins/metadata/meta_attribute.rb
35
+ - lib/serega/plugins/metadata/metadata.rb
36
+ - lib/serega/plugins/metadata/validations/check_block.rb
37
+ - lib/serega/plugins/metadata/validations/check_opt_hide_empty.rb
38
+ - lib/serega/plugins/metadata/validations/check_opt_hide_nil.rb
39
+ - lib/serega/plugins/metadata/validations/check_opts.rb
40
+ - lib/serega/plugins/metadata/validations/check_path.rb
41
+ - lib/serega/plugins/preloads/lib/enum_deep_freeze.rb
42
+ - lib/serega/plugins/preloads/lib/format_user_preloads.rb
43
+ - lib/serega/plugins/preloads/lib/main_preload_path.rb
44
+ - lib/serega/plugins/preloads/lib/preloads_constructor.rb
45
+ - lib/serega/plugins/preloads/preloads.rb
46
+ - lib/serega/plugins/preloads/validations/check_opt_preload_path.rb
47
+ - lib/serega/plugins/presenter/presenter.rb
48
+ - lib/serega/plugins/root/root.rb
49
+ - lib/serega/plugins/string_modifiers/parse_string_modifiers.rb
50
+ - lib/serega/plugins/string_modifiers/string_modifiers.rb
51
+ - lib/serega/plugins/validate_modifiers/validate.rb
52
+ - lib/serega/plugins/validate_modifiers/validate_modifiers.rb
53
+ - lib/serega/utils/as_json.rb
54
+ - lib/serega/utils/enum_deep_dup.rb
55
+ - lib/serega/utils/to_hash.rb
56
+ - lib/serega/utils/to_json.rb
57
+ - lib/serega/validations/attribute/check_block.rb
58
+ - lib/serega/validations/attribute/check_name.rb
59
+ - lib/serega/validations/attribute/check_opt_hide.rb
60
+ - lib/serega/validations/attribute/check_opt_many.rb
61
+ - lib/serega/validations/attribute/check_opt_method.rb
62
+ - lib/serega/validations/attribute/check_opt_serializer.rb
63
+ - lib/serega/validations/attribute/check_opts.rb
64
+ - lib/serega/validations/check_allowed_keys.rb
65
+ - lib/serega/validations/check_opt_is_bool.rb
66
+ - lib/serega/validations/check_opt_is_hash.rb
67
+ - lib/serega/version.rb
68
+ homepage: https://github.com/aglushkov/serega
69
+ licenses:
70
+ - MIT
71
+ metadata:
72
+ homepage_uri: https://github.com/aglushkov/serega
73
+ source_code_uri: https://github.com/aglushkov/serega
74
+ changelog_uri: https://github.com/aglushkov/serega/CHANGELOG.md
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: 2.6.0
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ requirements: []
90
+ rubygems_version: 3.3.15
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: Serializes objects to hash
94
+ test_files: []