serega 0.1.1 → 0.1.4
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.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/serega/attribute.rb +10 -9
- data/lib/serega/plugins/activerecord_preloads/activerecord_preloads.rb +1 -1
- data/lib/serega/plugins/context_metadata/context_metadata.rb +6 -10
- data/lib/serega/plugins/hide_nil/hide_nil.rb +3 -3
- data/lib/serega/plugins/preloads/preloads.rb +3 -3
- data/lib/serega/validations/attribute/check_block.rb +35 -65
- data/lib/serega/validations/attribute/check_name.rb +39 -37
- data/lib/serega/validations/attribute/check_opt_const.rb +34 -0
- data/lib/serega/validations/attribute/check_opt_hide.rb +15 -13
- data/lib/serega/validations/attribute/check_opt_key.rb +26 -16
- data/lib/serega/validations/attribute/check_opt_many.rb +15 -13
- data/lib/serega/validations/attribute/check_opt_serializer.rb +26 -24
- data/lib/serega/validations/attribute/check_opt_value.rb +53 -0
- data/lib/serega/validations/check_attribute_params.rb +51 -0
- data/lib/serega/validations/check_initiate_params.rb +26 -0
- data/lib/serega/validations/check_serialize_params.rb +29 -0
- data/lib/serega/validations/utils/check_allowed_keys.rb +17 -0
- data/lib/serega/validations/utils/check_opt_is_bool.rb +18 -0
- data/lib/serega/validations/utils/check_opt_is_hash.rb +18 -0
- data/lib/serega/validations/utils/check_opt_is_string_or_symbol.rb +18 -0
- data/lib/serega.rb +47 -11
- metadata +11 -6
- data/lib/serega/validations/attribute/check_opts.rb +0 -36
- data/lib/serega/validations/check_allowed_keys.rb +0 -13
- data/lib/serega/validations/check_opt_is_bool.rb +0 -14
- data/lib/serega/validations/check_opt_is_hash.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad827e730d35f4e1805b7a0c59e8a8eeec87a91bb426ada370ea4a632516f40c
|
4
|
+
data.tar.gz: 681deb3a954453740ac3256614684601aeb18027423352ca05cc62c82ff37784
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f279fecc4038a162b33d97001fa993758eb4d687c0a7b83f9555f20781e3ece12b1381ba9765993cf5a4d7a31a5dee66f29d3279e1198a6ddf6b6d19b977682
|
7
|
+
data.tar.gz: c1ed8f5f7e06ff2df08f2f5fb8ee587d062e3197399475c55d1383ab0fcb6c4c8f5224363ef202ecccdab063964a9e5cf98581ecdacfa5ac5caafa02277c93c6
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.4
|
data/lib/serega/attribute.rb
CHANGED
@@ -33,11 +33,11 @@ class Serega
|
|
33
33
|
# @param block [Proc] Proc that receives object and context and finds attribute value
|
34
34
|
#
|
35
35
|
def initialize(name:, opts: {}, block: nil)
|
36
|
-
|
36
|
+
self.class.serializer_class::CheckAttributeParams.new(name, opts, block).validate
|
37
37
|
|
38
38
|
@name = name.to_sym
|
39
39
|
@opts = Utils::EnumDeepDup.call(opts)
|
40
|
-
@block =
|
40
|
+
@block = block
|
41
41
|
end
|
42
42
|
|
43
43
|
# @return [Symbol] Object method name to will be used to get attribute value unless block provided
|
@@ -77,7 +77,7 @@ class Serega
|
|
77
77
|
def value_block
|
78
78
|
return @value_block if instance_variable_defined?(:@value_block)
|
79
79
|
|
80
|
-
@value_block = block || keyword_block
|
80
|
+
@value_block = block || opts[:value] || const_block || keyword_block
|
81
81
|
end
|
82
82
|
|
83
83
|
#
|
@@ -112,16 +112,17 @@ class Serega
|
|
112
112
|
|
113
113
|
private
|
114
114
|
|
115
|
+
def const_block
|
116
|
+
return unless opts.key?(:const)
|
117
|
+
|
118
|
+
const = opts[:const]
|
119
|
+
proc { const }
|
120
|
+
end
|
121
|
+
|
115
122
|
def keyword_block
|
116
123
|
key_method_name = key
|
117
124
|
proc { |object| object.public_send(key_method_name) }
|
118
125
|
end
|
119
|
-
|
120
|
-
def check(name, opts, block)
|
121
|
-
CheckName.call(name)
|
122
|
-
CheckOpts.call(opts, self.class.serializer_class.config[:attribute_keys])
|
123
|
-
CheckBlock.call(opts, block)
|
124
|
-
end
|
125
126
|
end
|
126
127
|
|
127
128
|
extend Serega::Helpers::SerializerClassHelper
|
@@ -14,8 +14,8 @@ class Serega
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def self.load_plugin(serializer_class, **_opts)
|
17
|
-
serializer_class.include(InstanceMethods)
|
18
17
|
serializer_class::Convert.include(ConvertInstanceMethods)
|
18
|
+
serializer_class::CheckSerializeParams.extend(CheckSerializeParamsClassMethods)
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.after_load_plugin(serializer_class, **opts)
|
@@ -25,16 +25,12 @@ class Serega
|
|
25
25
|
config[:serialize_keys] << meta_key
|
26
26
|
end
|
27
27
|
|
28
|
-
module
|
29
|
-
def
|
30
|
-
meta_key = self.class.config[:context_metadata][:key]
|
31
|
-
meta = opts[meta_key]
|
32
|
-
|
33
|
-
if meta && !meta.is_a?(Hash)
|
34
|
-
raise Serega::Error, "Option :#{meta_key} must be a Hash, but #{meta.class} was given"
|
35
|
-
end
|
36
|
-
|
28
|
+
module CheckSerializeParamsClassMethods
|
29
|
+
def check_opts(opts)
|
37
30
|
super
|
31
|
+
|
32
|
+
meta_key = serializer_class.config[:context_metadata][:key]
|
33
|
+
Validations::Utils::CheckOptIsHash.call(opts, meta_key)
|
38
34
|
end
|
39
35
|
end
|
40
36
|
|
@@ -22,7 +22,7 @@ class Serega
|
|
22
22
|
#
|
23
23
|
def self.load_plugin(serializer_class, **_opts)
|
24
24
|
serializer_class::Attribute.include(AttributeMethods)
|
25
|
-
serializer_class::
|
25
|
+
serializer_class::CheckAttributeParams.include(CheckAttributeParamsInstanceMethods)
|
26
26
|
serializer_class::ConvertItem.extend(ConvertItemClassMethods)
|
27
27
|
end
|
28
28
|
|
@@ -37,10 +37,10 @@ class Serega
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
module
|
40
|
+
module CheckAttributeParamsInstanceMethods
|
41
41
|
private
|
42
42
|
|
43
|
-
def
|
43
|
+
def check_opts
|
44
44
|
super
|
45
45
|
CheckOptHideNil.call(opts)
|
46
46
|
end
|
@@ -23,7 +23,7 @@ class Serega
|
|
23
23
|
serializer_class.include(InstanceMethods)
|
24
24
|
serializer_class::Attribute.include(AttributeMethods)
|
25
25
|
|
26
|
-
serializer_class::
|
26
|
+
serializer_class::CheckAttributeParams.include(CheckAttributeParamsInstanceMethods)
|
27
27
|
|
28
28
|
require_relative "./lib/enum_deep_freeze"
|
29
29
|
require_relative "./lib/format_user_preloads"
|
@@ -85,10 +85,10 @@ class Serega
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
-
module
|
88
|
+
module CheckAttributeParamsInstanceMethods
|
89
89
|
private
|
90
90
|
|
91
|
-
def
|
91
|
+
def check_opts
|
92
92
|
super
|
93
93
|
CheckOptPreloadPath.call(opts)
|
94
94
|
end
|
@@ -1,79 +1,49 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Serega
|
4
|
-
|
5
|
-
|
6
|
-
class
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
4
|
+
module Validations
|
5
|
+
module Attribute
|
6
|
+
class CheckBlock
|
7
|
+
class << self
|
8
|
+
#
|
9
|
+
# Checks :value option or a block provided with attribute
|
10
|
+
# Must have up to two arguments - object and context.
|
11
|
+
# It should not have any *rest or **key arguments
|
12
|
+
#
|
13
|
+
# @example without arguments
|
14
|
+
# attribute(:email) { CONSTANT_EMAIL }
|
15
|
+
#
|
16
|
+
# @example with one argument
|
17
|
+
# attribute(:email) { |obj| obj.confirmed_email }
|
18
|
+
#
|
19
|
+
# @example with two arguments
|
20
|
+
# attribute(:email) { |obj, context| context['is_current'] ? obj.email : nil }
|
21
|
+
#
|
22
|
+
# @param opts [Proc] Attribute opts, we will check :value option
|
23
|
+
# @param block [Proc] Block that returns serialized attribute value
|
24
|
+
#
|
25
|
+
# @raise [Error] Error that block has invalid arguments
|
26
|
+
#
|
27
|
+
# @return [void]
|
28
|
+
#
|
29
|
+
def call(block)
|
30
|
+
return unless block
|
30
31
|
|
31
|
-
if block
|
32
32
|
check_block(block)
|
33
|
-
elsif opts.key?(:value)
|
34
|
-
check_value(opts[:value])
|
35
33
|
end
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def check_both_provided(opts, block)
|
41
|
-
if opts.key?(:value) && block
|
42
|
-
raise Error, both_error
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def check_block(block)
|
47
|
-
params = block.parameters
|
48
|
-
return if (params.count <= 2) && params.all? { |par| par[0] == :opt }
|
49
|
-
|
50
|
-
raise Error, block_error
|
51
|
-
end
|
52
34
|
|
53
|
-
|
54
|
-
raise Error, value_error unless value.is_a?(Proc)
|
35
|
+
private
|
55
36
|
|
56
|
-
|
37
|
+
def check_block(block)
|
38
|
+
params = block.parameters
|
39
|
+
return if (params.count <= 2) && params.all? { |par| par[0] == :opt }
|
57
40
|
|
58
|
-
|
59
|
-
return if (params.count == 2) && params.all? { |par| par[0] == :req }
|
60
|
-
elsif (params.count <= 2) && params.all? { |par| par[0] == :opt }
|
61
|
-
return
|
41
|
+
raise Error, block_error
|
62
42
|
end
|
63
43
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
def block_error
|
68
|
-
"Block can have maximum two regular parameters (no **keyword or *array args)"
|
69
|
-
end
|
70
|
-
|
71
|
-
def value_error
|
72
|
-
"Option :value must be a Proc that is able to accept two parameters (no **keyword or *array args)"
|
73
|
-
end
|
74
|
-
|
75
|
-
def both_error
|
76
|
-
"Block and a :value option can not be provided together"
|
44
|
+
def block_error
|
45
|
+
"Block can have maximum two regular parameters (no **keyword or *array args)"
|
46
|
+
end
|
77
47
|
end
|
78
48
|
end
|
79
49
|
end
|
@@ -1,43 +1,45 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Serega
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
4
|
+
module Validations
|
5
|
+
module Attribute
|
6
|
+
class CheckName
|
7
|
+
FORMAT_ONE_CHAR = /\A[a-zA-Z0-9]\z/
|
8
|
+
FORMAT_MANY_CHARS = /\A[a-zA-Z0-9][a-zA-Z0-9_-]*?[a-zA-Z0-9]\z/ # allow '-' and '_' in the middle
|
9
|
+
|
10
|
+
private_constant :FORMAT_ONE_CHAR, :FORMAT_MANY_CHARS
|
11
|
+
|
12
|
+
class << self
|
13
|
+
#
|
14
|
+
# Checks allowed characters.
|
15
|
+
# Globally allowed characters: "a-z", "A-Z", "0-9".
|
16
|
+
# Minus and low line "-", "_" also allowed except as the first or last character.
|
17
|
+
#
|
18
|
+
# @param name [String, Symbol] Attribute name
|
19
|
+
#
|
20
|
+
# @raise [Error] when name has invalid format
|
21
|
+
# @return [void]
|
22
|
+
#
|
23
|
+
def call(name)
|
24
|
+
name = name.to_s
|
25
|
+
|
26
|
+
valid =
|
27
|
+
case name.size
|
28
|
+
when 0 then false
|
29
|
+
when 1 then name.match?(FORMAT_ONE_CHAR)
|
30
|
+
else name.match?(FORMAT_MANY_CHARS)
|
31
|
+
end
|
32
|
+
|
33
|
+
return if valid
|
34
|
+
|
35
|
+
raise Error, message(name)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def message(name)
|
41
|
+
%(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)
|
42
|
+
end
|
41
43
|
end
|
42
44
|
end
|
43
45
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module Validations
|
5
|
+
module Attribute
|
6
|
+
class CheckOptConst
|
7
|
+
#
|
8
|
+
# Checks attribute :const option
|
9
|
+
#
|
10
|
+
# @param opts [Hash] Attribute options
|
11
|
+
#
|
12
|
+
# @raise [Error] Attribute validation error
|
13
|
+
#
|
14
|
+
# @return [void]
|
15
|
+
#
|
16
|
+
class << self
|
17
|
+
def call(opts, block = nil)
|
18
|
+
return unless opts.key?(:const)
|
19
|
+
|
20
|
+
check_usage_with_other_params(opts, block)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def check_usage_with_other_params(opts, block)
|
26
|
+
raise Error, "Option :const can not be used together with option :key" if opts.key?(:key)
|
27
|
+
raise Error, "Option :const can not be used together with option :value" if opts.key?(:value)
|
28
|
+
raise Error, "Option :const can not be used together with block" if block
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,19 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Serega
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
4
|
+
module Validations
|
5
|
+
module Attribute
|
6
|
+
class CheckOptHide
|
7
|
+
#
|
8
|
+
# Checks attribute :hide 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 self.call(opts)
|
17
|
+
Utils::CheckOptIsBool.call(opts, :hide)
|
18
|
+
end
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
@@ -1,24 +1,34 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Serega
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
4
|
+
module Validations
|
5
|
+
module Attribute
|
6
|
+
class CheckOptKey
|
7
|
+
#
|
8
|
+
# Checks attribute :key option
|
9
|
+
#
|
10
|
+
# @param opts [Hash] Attribute options
|
11
|
+
#
|
12
|
+
# @raise [Error] Error that option has invalid value
|
13
|
+
#
|
14
|
+
# @return [void]
|
15
|
+
#
|
16
|
+
class << self
|
17
|
+
def call(opts, block = nil)
|
18
|
+
return unless opts.key?(:key)
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
+
check_usage_with_other_params(opts, block)
|
21
|
+
Utils::CheckOptIsStringOrSymbol.call(opts, :key)
|
22
|
+
end
|
20
23
|
|
21
|
-
|
24
|
+
private
|
25
|
+
|
26
|
+
def check_usage_with_other_params(opts, block)
|
27
|
+
raise Error, "Option :key can not be used together with option :const" if opts.key?(:const)
|
28
|
+
raise Error, "Option :key can not be used together with option :value" if opts.key?(:value)
|
29
|
+
raise Error, "Option :key can not be used together with block" if block
|
30
|
+
end
|
31
|
+
end
|
22
32
|
end
|
23
33
|
end
|
24
34
|
end
|
@@ -1,19 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Serega
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
4
|
+
module Validations
|
5
|
+
module Attribute
|
6
|
+
class CheckOptMany
|
7
|
+
#
|
8
|
+
# Checks attribute :many 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 self.call(opts)
|
17
|
+
Utils::CheckOptIsBool.call(opts, :many)
|
18
|
+
end
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
@@ -1,34 +1,36 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Serega
|
4
|
-
|
5
|
-
|
6
|
-
class
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
4
|
+
module Validations
|
5
|
+
module Attribute
|
6
|
+
class CheckOptSerializer
|
7
|
+
class << self
|
8
|
+
#
|
9
|
+
# Checks attribute :serializer option
|
10
|
+
#
|
11
|
+
# @param opts [Hash] Attribute options
|
12
|
+
#
|
13
|
+
# @raise [Error] Error that option has invalid value
|
14
|
+
#
|
15
|
+
# @return [void]
|
16
|
+
#
|
17
|
+
def call(opts)
|
18
|
+
return unless opts.key?(:serializer)
|
18
19
|
|
19
|
-
|
20
|
-
|
20
|
+
value = opts[:serializer]
|
21
|
+
return if valid_serializer?(value)
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
23
|
+
raise Error, "Invalid option :serializer => #{value.inspect}." \
|
24
|
+
" Can be a Serega subclass, a String or a Proc without arguments"
|
25
|
+
end
|
25
26
|
|
26
|
-
|
27
|
+
private
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
def valid_serializer?(value)
|
30
|
+
value.is_a?(String) ||
|
31
|
+
(value.is_a?(Proc) && (value.parameters.count == 0)) ||
|
32
|
+
(value.is_a?(Class) && (value < Serega))
|
33
|
+
end
|
32
34
|
end
|
33
35
|
end
|
34
36
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module Validations
|
5
|
+
module Attribute
|
6
|
+
class CheckOptValue
|
7
|
+
#
|
8
|
+
# Checks attribute :value option
|
9
|
+
#
|
10
|
+
# @param opts [Hash] Attribute options
|
11
|
+
#
|
12
|
+
# @raise [Error] Error that option has invalid value
|
13
|
+
#
|
14
|
+
# @return [void]
|
15
|
+
#
|
16
|
+
class << self
|
17
|
+
def call(opts, block = nil)
|
18
|
+
return unless opts.key?(:value)
|
19
|
+
|
20
|
+
check_usage_with_other_params(opts, block)
|
21
|
+
check_proc(opts[:value])
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def check_usage_with_other_params(opts, block)
|
27
|
+
raise Error, "Option :value can not be used together with option :key" if opts.key?(:key)
|
28
|
+
raise Error, "Option :value can not be used together with option :const" if opts.key?(:const)
|
29
|
+
raise Error, "Option :value can not be used together with block" if block
|
30
|
+
end
|
31
|
+
|
32
|
+
def check_proc(value)
|
33
|
+
raise Error, value_error unless value.is_a?(Proc)
|
34
|
+
|
35
|
+
params = value.parameters
|
36
|
+
|
37
|
+
if value.lambda?
|
38
|
+
return if (params.count == 2) && params.all? { |par| par[0] == :req }
|
39
|
+
elsif (params.count <= 2) && params.all? { |par| par[0] == :opt }
|
40
|
+
return
|
41
|
+
end
|
42
|
+
|
43
|
+
raise Error, value_error
|
44
|
+
end
|
45
|
+
|
46
|
+
def value_error
|
47
|
+
"Option :value must be a Proc that is able to accept two parameters (no **keyword or *array args)"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module Validations
|
5
|
+
class CheckAttributeParams
|
6
|
+
module InstanceMethods
|
7
|
+
attr_reader :name, :opts, :block
|
8
|
+
|
9
|
+
def initialize(name, opts, block)
|
10
|
+
@name = name
|
11
|
+
@opts = opts
|
12
|
+
@block = block
|
13
|
+
end
|
14
|
+
|
15
|
+
def validate
|
16
|
+
check_name
|
17
|
+
check_opts
|
18
|
+
check_block
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def check_name
|
24
|
+
Attribute::CheckName.call(name)
|
25
|
+
end
|
26
|
+
|
27
|
+
def check_opts
|
28
|
+
Utils::CheckAllowedKeys.call(opts, allowed_opts_keys)
|
29
|
+
|
30
|
+
Attribute::CheckOptConst.call(opts, block)
|
31
|
+
Attribute::CheckOptHide.call(opts)
|
32
|
+
Attribute::CheckOptKey.call(opts, block)
|
33
|
+
Attribute::CheckOptMany.call(opts)
|
34
|
+
Attribute::CheckOptSerializer.call(opts)
|
35
|
+
Attribute::CheckOptValue.call(opts, block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def check_block
|
39
|
+
Attribute::CheckBlock.call(block)
|
40
|
+
end
|
41
|
+
|
42
|
+
def allowed_opts_keys
|
43
|
+
self.class.serializer_class.config[:attribute_keys]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
include InstanceMethods
|
48
|
+
extend Serega::Helpers::SerializerClassHelper
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module Validations
|
5
|
+
class CheckInitiateParams
|
6
|
+
module ClassMethods
|
7
|
+
def call(opts)
|
8
|
+
check_opts(opts)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def check_opts(opts)
|
14
|
+
Utils::CheckAllowedKeys.call(opts, allowed_opts_keys)
|
15
|
+
end
|
16
|
+
|
17
|
+
def allowed_opts_keys
|
18
|
+
serializer_class.config[:initiate_keys]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
extend ClassMethods
|
23
|
+
extend Serega::Helpers::SerializerClassHelper
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module Validations
|
5
|
+
class CheckSerializeParams
|
6
|
+
module ClassMethods
|
7
|
+
def call(opts)
|
8
|
+
check_opts(opts)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def check_opts(opts)
|
14
|
+
Utils::CheckAllowedKeys.call(opts, allowed_opts_keys)
|
15
|
+
|
16
|
+
Utils::CheckOptIsHash.call(opts, :context)
|
17
|
+
Utils::CheckOptIsBool.call(opts, :many)
|
18
|
+
end
|
19
|
+
|
20
|
+
def allowed_opts_keys
|
21
|
+
serializer_class.config[:serialize_keys]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
extend ClassMethods
|
26
|
+
extend Serega::Helpers::SerializerClassHelper
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module Validations
|
5
|
+
module Utils
|
6
|
+
class CheckAllowedKeys
|
7
|
+
def self.call(opts, allowed_keys)
|
8
|
+
opts.each_key do |key|
|
9
|
+
next if allowed_keys.include?(key)
|
10
|
+
|
11
|
+
raise Error, "Invalid option #{key.inspect}. Allowed options are: #{allowed_keys.map(&:inspect).join(", ")}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module Validations
|
5
|
+
module Utils
|
6
|
+
class CheckOptIsBool
|
7
|
+
def self.call(opts, key)
|
8
|
+
return unless opts.key?(key)
|
9
|
+
|
10
|
+
value = opts[key]
|
11
|
+
return if value.equal?(true) || value.equal?(false)
|
12
|
+
|
13
|
+
raise Error, "Invalid option #{key.inspect} => #{value.inspect}. Must have a boolean value"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module Validations
|
5
|
+
module Utils
|
6
|
+
class CheckOptIsHash
|
7
|
+
def self.call(opts, key)
|
8
|
+
return unless opts.key?(key)
|
9
|
+
|
10
|
+
value = opts[key]
|
11
|
+
return if value.is_a?(Hash)
|
12
|
+
|
13
|
+
raise Error, "Invalid option #{key.inspect} => #{value.inspect}. Must have a Hash value"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module Validations
|
5
|
+
module Utils
|
6
|
+
class CheckOptIsStringOrSymbol
|
7
|
+
def self.call(opts, key)
|
8
|
+
return unless opts.key?(key)
|
9
|
+
|
10
|
+
value = opts[key]
|
11
|
+
return if value.is_a?(String) || value.is_a?(Symbol)
|
12
|
+
|
13
|
+
raise Error, "Invalid option #{key.inspect} => #{value.inspect}. Must be a String or a Symbol"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/serega.rb
CHANGED
@@ -21,16 +21,21 @@ require_relative "serega/utils/to_json"
|
|
21
21
|
require_relative "serega/utils/as_json"
|
22
22
|
|
23
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"
|
24
|
+
require_relative "serega/validations/utils/check_allowed_keys"
|
25
|
+
require_relative "serega/validations/utils/check_opt_is_bool"
|
26
|
+
require_relative "serega/validations/utils/check_opt_is_hash"
|
27
|
+
require_relative "serega/validations/utils/check_opt_is_string_or_symbol"
|
27
28
|
require_relative "serega/validations/attribute/check_block"
|
28
29
|
require_relative "serega/validations/attribute/check_name"
|
30
|
+
require_relative "serega/validations/attribute/check_opt_const"
|
29
31
|
require_relative "serega/validations/attribute/check_opt_hide"
|
30
32
|
require_relative "serega/validations/attribute/check_opt_key"
|
31
33
|
require_relative "serega/validations/attribute/check_opt_many"
|
32
34
|
require_relative "serega/validations/attribute/check_opt_serializer"
|
33
|
-
require_relative "serega/validations/attribute/
|
35
|
+
require_relative "serega/validations/attribute/check_opt_value"
|
36
|
+
require_relative "serega/validations/check_attribute_params"
|
37
|
+
require_relative "serega/validations/check_initiate_params"
|
38
|
+
require_relative "serega/validations/check_serialize_params"
|
34
39
|
|
35
40
|
require_relative "serega/config"
|
36
41
|
require_relative "serega/convert"
|
@@ -43,13 +48,25 @@ class Serega
|
|
43
48
|
{
|
44
49
|
plugins: [],
|
45
50
|
initiate_keys: %i[only with except],
|
46
|
-
attribute_keys: %i[key value serializer many hide],
|
51
|
+
attribute_keys: %i[key value serializer many hide const],
|
47
52
|
serialize_keys: %i[context many],
|
48
53
|
max_cached_map_per_serializer_count: 50,
|
49
54
|
to_json: ->(data) { Utils::ToJSON.call(data) }
|
50
55
|
}
|
51
56
|
)
|
52
57
|
|
58
|
+
check_attribute_params_class = Class.new(Validations::CheckAttributeParams)
|
59
|
+
check_attribute_params_class.serializer_class = self
|
60
|
+
const_set(:CheckAttributeParams, check_attribute_params_class)
|
61
|
+
|
62
|
+
check_initiate_params_class = Class.new(Validations::CheckInitiateParams)
|
63
|
+
check_initiate_params_class.serializer_class = self
|
64
|
+
const_set(:CheckInitiateParams, check_initiate_params_class)
|
65
|
+
|
66
|
+
check_serialize_params_class = Class.new(Validations::CheckSerializeParams)
|
67
|
+
check_serialize_params_class.serializer_class = self
|
68
|
+
const_set(:CheckSerializeParams, check_serialize_params_class)
|
69
|
+
|
53
70
|
# Core serializer class methods
|
54
71
|
module ClassMethods
|
55
72
|
# @return [Config] current serializer config
|
@@ -77,6 +94,18 @@ class Serega
|
|
77
94
|
convert_item_class.serializer_class = subclass
|
78
95
|
subclass.const_set(:ConvertItem, convert_item_class)
|
79
96
|
|
97
|
+
check_attribute_params_class = Class.new(self::CheckAttributeParams)
|
98
|
+
check_attribute_params_class.serializer_class = subclass
|
99
|
+
subclass.const_set(:CheckAttributeParams, check_attribute_params_class)
|
100
|
+
|
101
|
+
check_initiate_params_class = Class.new(self::CheckInitiateParams)
|
102
|
+
check_initiate_params_class.serializer_class = subclass
|
103
|
+
subclass.const_set(:CheckInitiateParams, check_initiate_params_class)
|
104
|
+
|
105
|
+
check_serialize_params_class = Class.new(self::CheckSerializeParams)
|
106
|
+
check_serialize_params_class.serializer_class = subclass
|
107
|
+
subclass.const_set(:CheckSerializeParams, check_serialize_params_class)
|
108
|
+
|
80
109
|
# Assign same attributes
|
81
110
|
attributes.each_value do |attr|
|
82
111
|
subclass.attribute(attr.name, **attr.opts, &attr.block)
|
@@ -167,11 +196,15 @@ class Serega
|
|
167
196
|
attribute(name, serializer: serializer, **opts, &block)
|
168
197
|
end
|
169
198
|
|
170
|
-
def
|
199
|
+
def call(object, opts = FROZEN_EMPTY_HASH)
|
171
200
|
initiate_keys = config[:initiate_keys]
|
172
201
|
new(opts.slice(*initiate_keys)).to_h(object, opts.except(*initiate_keys))
|
173
202
|
end
|
174
203
|
|
204
|
+
def to_h(object, opts = FROZEN_EMPTY_HASH)
|
205
|
+
call(object, opts)
|
206
|
+
end
|
207
|
+
|
175
208
|
def to_json(object, opts = FROZEN_EMPTY_HASH)
|
176
209
|
initiate_keys = config[:initiate_keys]
|
177
210
|
new(opts.slice(*initiate_keys)).to_json(object, opts.except(*initiate_keys))
|
@@ -197,7 +230,7 @@ class Serega
|
|
197
230
|
# @param with [Array, Hash, String, Symbol] Attributes (usually hidden) to serialize additionally
|
198
231
|
#
|
199
232
|
def initialize(opts = FROZEN_EMPTY_HASH)
|
200
|
-
|
233
|
+
self.class::CheckInitiateParams.call(opts)
|
201
234
|
opts = prepare_modifiers(opts) if opts && (opts != FROZEN_EMPTY_HASH)
|
202
235
|
@opts = opts
|
203
236
|
end
|
@@ -210,15 +243,18 @@ class Serega
|
|
210
243
|
#
|
211
244
|
# @return [Hash] Serialization result
|
212
245
|
#
|
213
|
-
def
|
214
|
-
|
215
|
-
CheckOptIsHash.call(opts, :context)
|
216
|
-
CheckOptIsBool.call(opts, :many)
|
246
|
+
def call(object, opts = {})
|
247
|
+
self.class::CheckSerializeParams.call(opts)
|
217
248
|
opts[:context] ||= {}
|
218
249
|
|
219
250
|
self.class::Convert.call(object, **opts, map: map)
|
220
251
|
end
|
221
252
|
|
253
|
+
# @see #call
|
254
|
+
def to_h(object, opts = {})
|
255
|
+
call(object, opts)
|
256
|
+
end
|
257
|
+
|
222
258
|
#
|
223
259
|
# Serializes provided object to json
|
224
260
|
#
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: serega
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrey Glushkov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-07-
|
11
|
+
date: 2022-07-25 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -56,14 +56,19 @@ files:
|
|
56
56
|
- lib/serega/utils/to_json.rb
|
57
57
|
- lib/serega/validations/attribute/check_block.rb
|
58
58
|
- lib/serega/validations/attribute/check_name.rb
|
59
|
+
- lib/serega/validations/attribute/check_opt_const.rb
|
59
60
|
- lib/serega/validations/attribute/check_opt_hide.rb
|
60
61
|
- lib/serega/validations/attribute/check_opt_key.rb
|
61
62
|
- lib/serega/validations/attribute/check_opt_many.rb
|
62
63
|
- lib/serega/validations/attribute/check_opt_serializer.rb
|
63
|
-
- lib/serega/validations/attribute/
|
64
|
-
- lib/serega/validations/
|
65
|
-
- lib/serega/validations/
|
66
|
-
- lib/serega/validations/
|
64
|
+
- lib/serega/validations/attribute/check_opt_value.rb
|
65
|
+
- lib/serega/validations/check_attribute_params.rb
|
66
|
+
- lib/serega/validations/check_initiate_params.rb
|
67
|
+
- lib/serega/validations/check_serialize_params.rb
|
68
|
+
- lib/serega/validations/utils/check_allowed_keys.rb
|
69
|
+
- lib/serega/validations/utils/check_opt_is_bool.rb
|
70
|
+
- lib/serega/validations/utils/check_opt_is_hash.rb
|
71
|
+
- lib/serega/validations/utils/check_opt_is_string_or_symbol.rb
|
67
72
|
- lib/serega/version.rb
|
68
73
|
homepage: https://github.com/aglushkov/serega
|
69
74
|
licenses:
|
@@ -1,36 +0,0 @@
|
|
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
|
-
CheckOptKey.call(opts)
|
28
|
-
CheckOptMany.call(opts)
|
29
|
-
CheckOptSerializer.call(opts)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
extend ClassMethods
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,13 +0,0 @@
|
|
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
|
@@ -1,14 +0,0 @@
|
|
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
|
@@ -1,14 +0,0 @@
|
|
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
|