serega 0.8.3 → 0.10.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.
- checksums.yaml +4 -4
- data/README.md +60 -10
- data/VERSION +1 -1
- data/lib/serega/attribute.rb +9 -1
- data/lib/serega/config.rb +16 -0
- data/lib/serega/object_serializer.rb +13 -1
- data/lib/serega/plugins/batch/batch.rb +8 -7
- data/lib/serega/plugins/batch/lib/loader.rb +3 -0
- data/lib/serega/plugins/if/if.rb +168 -0
- data/lib/serega/plugins/if/validations/check_opt_if.rb +79 -0
- data/lib/serega/plugins/if/validations/check_opt_if_value.rb +84 -0
- data/lib/serega/plugins/if/validations/check_opt_unless.rb +88 -0
- data/lib/serega/plugins/if/validations/check_opt_unless_value.rb +84 -0
- data/lib/serega/plugins/metadata/meta_attribute.rb +10 -2
- data/lib/serega/plugins/metadata/metadata.rb +15 -13
- data/lib/serega/plugins/metadata/validations/check_path.rb +10 -17
- data/lib/serega/plugins/preloads/preloads.rb +2 -0
- data/lib/serega/plugins/presenter/presenter.rb +10 -8
- data/lib/serega/plugins/string_modifiers/parse_string_modifiers.rb +46 -57
- data/lib/serega/plugins/string_modifiers/string_modifiers.rb +3 -7
- data/lib/serega/utils/enum_deep_dup.rb +2 -2
- data/lib/serega/validations/attribute/check_name.rb +8 -21
- data/lib/serega/validations/check_attribute_params.rb +10 -1
- data/lib/serega.rb +72 -48
- metadata +8 -4
- data/lib/serega/plugins/hide_nil/hide_nil.rb +0 -106
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module SeregaPlugins
|
5
|
+
module If
|
6
|
+
#
|
7
|
+
# Validator for attribute :unless_value option
|
8
|
+
#
|
9
|
+
class CheckOptUnlessValue
|
10
|
+
class << self
|
11
|
+
#
|
12
|
+
# Checks attribute :unless_value option that must be [nil, Symbol, Proc, #call]
|
13
|
+
#
|
14
|
+
# @param opts [Hash] Attribute options
|
15
|
+
#
|
16
|
+
# @raise [SeregaError] Attribute validation error
|
17
|
+
#
|
18
|
+
# @return [void]
|
19
|
+
#
|
20
|
+
def call(opts)
|
21
|
+
return unless opts.key?(:unless_value)
|
22
|
+
|
23
|
+
check_usage_with_other_params(opts)
|
24
|
+
check_type(opts[:unless_value])
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def check_type(value)
|
30
|
+
return if value.is_a?(Symbol)
|
31
|
+
|
32
|
+
raise SeregaError, must_be_callable unless value.respond_to?(:call)
|
33
|
+
|
34
|
+
if value.is_a?(Proc)
|
35
|
+
check_block(value)
|
36
|
+
else
|
37
|
+
check_callable(value)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def check_usage_with_other_params(opts)
|
42
|
+
raise SeregaError, "Option :unless_value can not be used together with option :serializer" if opts.key?(:serializer)
|
43
|
+
end
|
44
|
+
|
45
|
+
def check_block(block)
|
46
|
+
return if valid_parameters?(block, accepted_count: 0..2)
|
47
|
+
|
48
|
+
raise SeregaError, block_parameters_error
|
49
|
+
end
|
50
|
+
|
51
|
+
def check_callable(callable)
|
52
|
+
return if valid_parameters?(callable.method(:call), accepted_count: 2..2)
|
53
|
+
|
54
|
+
raise SeregaError, callable_parameters_error
|
55
|
+
end
|
56
|
+
|
57
|
+
def valid_parameters?(data, accepted_count:)
|
58
|
+
params = data.parameters
|
59
|
+
accepted_count.include?(params.count) && valid_parameters_types?(params)
|
60
|
+
end
|
61
|
+
|
62
|
+
def valid_parameters_types?(params)
|
63
|
+
params.all? do |param|
|
64
|
+
type = param[0]
|
65
|
+
(type == :req) || (type == :opt)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def block_parameters_error
|
70
|
+
"Invalid attribute option :unless_value. When it is a Proc it can have maximum two regular parameters (object, context)"
|
71
|
+
end
|
72
|
+
|
73
|
+
def callable_parameters_error
|
74
|
+
"Invalid attribute option :unless_value. When it is a callable object it must have two regular parameters (object, context)"
|
75
|
+
end
|
76
|
+
|
77
|
+
def must_be_callable
|
78
|
+
"Invalid attribute option :unless_value. It must be a Symbol, a Proc or respond to :call"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -60,10 +60,18 @@ class Serega
|
|
60
60
|
private
|
61
61
|
|
62
62
|
def check(path, opts, block)
|
63
|
-
CheckPath.call(path)
|
64
|
-
CheckOpts.call(opts,
|
63
|
+
CheckPath.call(path) if check_attribute_name
|
64
|
+
CheckOpts.call(opts, attribute_keys)
|
65
65
|
CheckBlock.call(block)
|
66
66
|
end
|
67
|
+
|
68
|
+
def attribute_keys
|
69
|
+
self.class.serializer_class.config.metadata.attribute_keys
|
70
|
+
end
|
71
|
+
|
72
|
+
def check_attribute_name
|
73
|
+
self.class.serializer_class.config.check_attribute_name
|
74
|
+
end
|
67
75
|
end
|
68
76
|
|
69
77
|
extend Serega::SeregaHelpers::SerializerClassHelper
|
@@ -130,19 +130,6 @@ class Serega
|
|
130
130
|
# @see Serega::SeregaConfig
|
131
131
|
#
|
132
132
|
module ClassMethods
|
133
|
-
private def inherited(subclass)
|
134
|
-
super
|
135
|
-
|
136
|
-
meta_attribute_class = Class.new(self::MetaAttribute)
|
137
|
-
meta_attribute_class.serializer_class = subclass
|
138
|
-
subclass.const_set(:MetaAttribute, meta_attribute_class)
|
139
|
-
|
140
|
-
# Assign same metadata attributes
|
141
|
-
meta_attributes.each_value do |attr|
|
142
|
-
subclass.meta_attribute(*attr.path, **attr.opts, &attr.block)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
133
|
#
|
147
134
|
# List of added metadata attributes
|
148
135
|
#
|
@@ -165,6 +152,21 @@ class Serega
|
|
165
152
|
attribute = self::MetaAttribute.new(path: path, opts: opts, block: block)
|
166
153
|
meta_attributes[attribute.name] = attribute
|
167
154
|
end
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
def inherited(subclass)
|
159
|
+
super
|
160
|
+
|
161
|
+
meta_attribute_class = Class.new(self::MetaAttribute)
|
162
|
+
meta_attribute_class.serializer_class = subclass
|
163
|
+
subclass.const_set(:MetaAttribute, meta_attribute_class)
|
164
|
+
|
165
|
+
# Assign same metadata attributes
|
166
|
+
meta_attributes.each_value do |attr|
|
167
|
+
subclass.meta_attribute(*attr.path, **attr.opts, &attr.block)
|
168
|
+
end
|
169
|
+
end
|
168
170
|
end
|
169
171
|
|
170
172
|
#
|
@@ -8,16 +8,15 @@ class Serega
|
|
8
8
|
# Validator for meta_attribute :path parameter
|
9
9
|
#
|
10
10
|
class CheckPath
|
11
|
-
|
12
|
-
|
11
|
+
# Regexp for valid path
|
12
|
+
FORMAT = /\A[\w~-]+\z/
|
13
13
|
|
14
|
-
private_constant :
|
14
|
+
private_constant :FORMAT
|
15
15
|
|
16
16
|
class << self
|
17
17
|
#
|
18
|
-
# Checks allowed characters
|
19
|
-
#
|
20
|
-
# Minus and low line "-", "_" also allowed except as the first or last character.
|
18
|
+
# Checks allowed characters.
|
19
|
+
# Allowed characters: "a-z", "A-Z", "0-9", "_", "-", "~".
|
21
20
|
#
|
22
21
|
# @param path [Array<String, Symbol>] Metadata attribute path names
|
23
22
|
#
|
@@ -33,20 +32,14 @@ class Serega
|
|
33
32
|
def check_name(name)
|
34
33
|
name = name.to_s
|
35
34
|
|
36
|
-
|
37
|
-
case name.size
|
38
|
-
when 0 then false
|
39
|
-
when 1 then name.match?(FORMAT_ONE_CHAR)
|
40
|
-
else name.match?(FORMAT_MANY_CHARS)
|
41
|
-
end
|
42
|
-
|
43
|
-
return if valid
|
44
|
-
|
45
|
-
raise SeregaError, message(name)
|
35
|
+
raise SeregaError, message(name) unless FORMAT.match?(name)
|
46
36
|
end
|
47
37
|
|
48
38
|
def message(name)
|
49
|
-
|
39
|
+
<<~MESSAGE.tr("\n", "")
|
40
|
+
Invalid metadata path #{name.inspect}.
|
41
|
+
Allowed characters: "a-z", "A-Z", "0-9", "_", "-", "~"
|
42
|
+
MESSAGE
|
50
43
|
end
|
51
44
|
end
|
52
45
|
end
|
@@ -235,6 +235,8 @@ class Serega
|
|
235
235
|
@auto_hide_attribute_with_preloads = auto && !preloads.nil? && (preloads != false) && (preloads != {})
|
236
236
|
end
|
237
237
|
|
238
|
+
# Patched in:
|
239
|
+
# - plugin :batch (extension :preloads - skips auto preloads when batch option provided)
|
238
240
|
def get_preloads
|
239
241
|
preloads_provided = opts.key?(:preload)
|
240
242
|
preloads =
|
@@ -80,14 +80,6 @@ class Serega
|
|
80
80
|
# @see Serega
|
81
81
|
#
|
82
82
|
module ClassMethods
|
83
|
-
private def inherited(subclass)
|
84
|
-
super
|
85
|
-
|
86
|
-
presenter_class = Class.new(self::Presenter)
|
87
|
-
presenter_class.serializer_class = subclass
|
88
|
-
subclass.const_set(:Presenter, presenter_class)
|
89
|
-
end
|
90
|
-
|
91
83
|
# Overrides {Serega::ClassMethods#attribute} method, additionally adds method
|
92
84
|
# to Presenter to not hit {Serega::SeregaPlugins::Presenter::Presenter#method_missing}
|
93
85
|
# @see Serega::ClassMethods#attribute
|
@@ -96,6 +88,16 @@ class Serega
|
|
96
88
|
self::Presenter.def_delegator(:__getobj__, attribute.key) unless attribute.block
|
97
89
|
end
|
98
90
|
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def inherited(subclass)
|
95
|
+
super
|
96
|
+
|
97
|
+
presenter_class = Class.new(self::Presenter)
|
98
|
+
presenter_class.serializer_class = subclass
|
99
|
+
subclass.const_set(:Presenter, presenter_class)
|
100
|
+
end
|
99
101
|
end
|
100
102
|
|
101
103
|
#
|
@@ -25,72 +25,61 @@ class Serega
|
|
25
25
|
# Modifiers parser
|
26
26
|
#
|
27
27
|
class ParseStringModifiers
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
28
|
+
class << self
|
29
|
+
#
|
30
|
+
# Parses string modifiers
|
31
|
+
#
|
32
|
+
# @param fields [String]
|
33
|
+
#
|
34
|
+
# @return [Hash] parsed modifiers in form of nested hash
|
35
|
+
#
|
36
|
+
# @example
|
37
|
+
# parse("user") => { user: {} }
|
38
|
+
# parse("user(id)") => { user: { id: {} } }
|
39
|
+
# parse("user(id,name)") => { user: { id: {}, name: {} } }
|
40
|
+
# parse("user,comments") => { user: {}, comments: {} }
|
41
|
+
# parse("user(comments(text))") => { user: { comments: { text: {} } } }
|
42
|
+
def parse(fields)
|
43
|
+
res = {}
|
44
|
+
attribute = +""
|
45
|
+
char = +""
|
46
|
+
path_stack = nil
|
47
|
+
fields = StringIO.new(fields)
|
37
48
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
# parse("user(id,name)") => { user: { id: {}, name: {} } }
|
52
|
-
# parse("user,comments") => { user: {}, comments: {} }
|
53
|
-
# parse("user(comments(text))") => { user: { comments: { text: {} } } }
|
54
|
-
def parse(fields)
|
55
|
-
res = {}
|
56
|
-
attribute = +""
|
57
|
-
char = +""
|
58
|
-
path_stack = nil
|
59
|
-
fields = StringIO.new(fields)
|
60
|
-
|
61
|
-
while fields.read(1, char)
|
62
|
-
case char
|
63
|
-
when ","
|
64
|
-
add_attribute(res, path_stack, attribute, FROZEN_EMPTY_HASH)
|
65
|
-
when ")"
|
66
|
-
add_attribute(res, path_stack, attribute, FROZEN_EMPTY_HASH)
|
67
|
-
path_stack&.pop
|
68
|
-
when "("
|
69
|
-
name = add_attribute(res, path_stack, attribute, {})
|
70
|
-
(path_stack ||= []).push(name) if name
|
71
|
-
else
|
72
|
-
attribute.insert(-1, char)
|
49
|
+
while fields.read(1, char)
|
50
|
+
case char
|
51
|
+
when ","
|
52
|
+
add_attribute(res, path_stack, attribute, FROZEN_EMPTY_HASH)
|
53
|
+
when ")"
|
54
|
+
add_attribute(res, path_stack, attribute, FROZEN_EMPTY_HASH)
|
55
|
+
path_stack&.pop
|
56
|
+
when "("
|
57
|
+
name = add_attribute(res, path_stack, attribute, {})
|
58
|
+
(path_stack ||= []).push(name) if name
|
59
|
+
else
|
60
|
+
attribute.insert(-1, char)
|
61
|
+
end
|
73
62
|
end
|
74
|
-
end
|
75
63
|
|
76
|
-
|
64
|
+
add_attribute(res, path_stack, attribute, FROZEN_EMPTY_HASH)
|
77
65
|
|
78
|
-
|
79
|
-
|
66
|
+
res
|
67
|
+
end
|
80
68
|
|
81
|
-
|
69
|
+
private
|
82
70
|
|
83
|
-
|
84
|
-
|
85
|
-
|
71
|
+
def add_attribute(res, path_stack, attribute, nested_attributes = FROZEN_EMPTY_HASH)
|
72
|
+
attribute.strip!
|
73
|
+
return if attribute.empty?
|
86
74
|
|
87
|
-
|
88
|
-
|
75
|
+
name = attribute.to_sym
|
76
|
+
attribute.clear
|
89
77
|
|
90
|
-
|
91
|
-
|
78
|
+
current_attrs = (!path_stack || path_stack.empty?) ? res : res.dig(*path_stack)
|
79
|
+
current_attrs[name] = nested_attributes
|
92
80
|
|
93
|
-
|
81
|
+
name
|
82
|
+
end
|
94
83
|
end
|
95
84
|
end
|
96
85
|
end
|
@@ -29,14 +29,10 @@ class Serega
|
|
29
29
|
module InstanceMethods
|
30
30
|
private
|
31
31
|
|
32
|
-
def
|
33
|
-
|
34
|
-
opts.each_with_object({}) do |(key, value), obj|
|
35
|
-
value = ParseStringModifiers.call(value) if (key == :only) || (key == :except) || (key == :with)
|
36
|
-
obj[key] = value
|
37
|
-
end
|
32
|
+
def parse_modifier(value)
|
33
|
+
return ParseStringModifiers.parse(value) if value.is_a?(String)
|
38
34
|
|
39
|
-
super
|
35
|
+
super
|
40
36
|
end
|
41
37
|
end
|
42
38
|
end
|
@@ -38,8 +38,8 @@ class Serega
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def dup_array_values(duplicate_data)
|
41
|
-
duplicate_data.
|
42
|
-
|
41
|
+
duplicate_data.map! do |value|
|
42
|
+
value.is_a?(Enumerable) ? call(value) : value
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
@@ -7,19 +7,13 @@ class Serega
|
|
7
7
|
# Attribute `name` parameter validator
|
8
8
|
#
|
9
9
|
class CheckName
|
10
|
-
# Regexp for valid
|
11
|
-
|
12
|
-
|
13
|
-
# Regexp for valid multi-chars attribute name
|
14
|
-
FORMAT_MANY_CHARS = /\A[a-zA-Z0-9][a-zA-Z0-9_-]*?[a-zA-Z0-9]\z/ # allow '-' and '_' in the middle
|
15
|
-
|
16
|
-
private_constant :FORMAT_ONE_CHAR, :FORMAT_MANY_CHARS
|
10
|
+
# Regexp for valid attribute name
|
11
|
+
FORMAT = /\A[\w~-]+\z/
|
17
12
|
|
18
13
|
class << self
|
19
14
|
#
|
20
15
|
# Checks allowed characters.
|
21
|
-
#
|
22
|
-
# Minus and low line "-", "_" also allowed except as the first or last character.
|
16
|
+
# Allowed characters: "a-z", "A-Z", "0-9", "_", "-", "~".
|
23
17
|
#
|
24
18
|
# @param name [String, Symbol] Attribute name
|
25
19
|
#
|
@@ -28,23 +22,16 @@ class Serega
|
|
28
22
|
#
|
29
23
|
def call(name)
|
30
24
|
name = SeregaUtils::SymbolName.call(name)
|
31
|
-
|
32
|
-
valid =
|
33
|
-
case name.size
|
34
|
-
when 0 then false
|
35
|
-
when 1 then name.match?(FORMAT_ONE_CHAR)
|
36
|
-
else name.match?(FORMAT_MANY_CHARS)
|
37
|
-
end
|
38
|
-
|
39
|
-
return if valid
|
40
|
-
|
41
|
-
raise SeregaError, message(name)
|
25
|
+
raise SeregaError, message(name) unless FORMAT.match?(name)
|
42
26
|
end
|
43
27
|
|
44
28
|
private
|
45
29
|
|
46
30
|
def message(name)
|
47
|
-
|
31
|
+
<<~MESSAGE.tr("\n", "")
|
32
|
+
Invalid attribute name = #{name.inspect}.
|
33
|
+
Allowed characters: "a-z", "A-Z", "0-9", "_", "-", "~"
|
34
|
+
MESSAGE
|
48
35
|
end
|
49
36
|
end
|
50
37
|
end
|
@@ -41,7 +41,7 @@ class Serega
|
|
41
41
|
# Validates attribute params
|
42
42
|
#
|
43
43
|
def validate
|
44
|
-
check_name
|
44
|
+
check_name if check_attribute_name
|
45
45
|
check_opts
|
46
46
|
check_block
|
47
47
|
end
|
@@ -52,6 +52,11 @@ class Serega
|
|
52
52
|
Attribute::CheckName.call(name)
|
53
53
|
end
|
54
54
|
|
55
|
+
# Patched in:
|
56
|
+
# - plugin :batch (checks :batch option)
|
57
|
+
# - plugin :context_metadata (checks context metadata option which is :meta by default)
|
58
|
+
# - plugin :if (checks :if, :if_value, :unless, :unless_value options)
|
59
|
+
# - plugin :preloads (checks :preload option)
|
55
60
|
def check_opts
|
56
61
|
Utils::CheckAllowedKeys.call(opts, allowed_opts_keys)
|
57
62
|
|
@@ -71,6 +76,10 @@ class Serega
|
|
71
76
|
def allowed_opts_keys
|
72
77
|
self.class.serializer_class.config.attribute_keys
|
73
78
|
end
|
79
|
+
|
80
|
+
def check_attribute_name
|
81
|
+
self.class.serializer_class.config.check_attribute_name
|
82
|
+
end
|
74
83
|
end
|
75
84
|
|
76
85
|
include InstanceMethods
|
data/lib/serega.rb
CHANGED
@@ -70,49 +70,6 @@ class Serega
|
|
70
70
|
# Returns current config
|
71
71
|
# @return [SeregaConfig] current serializer config
|
72
72
|
attr_reader :config
|
73
|
-
|
74
|
-
private def inherited(subclass)
|
75
|
-
config_class = Class.new(self::SeregaConfig)
|
76
|
-
config_class.serializer_class = subclass
|
77
|
-
subclass.const_set(:SeregaConfig, config_class)
|
78
|
-
subclass.instance_variable_set(:@config, subclass::SeregaConfig.new(config.opts))
|
79
|
-
|
80
|
-
attribute_class = Class.new(self::SeregaAttribute)
|
81
|
-
attribute_class.serializer_class = subclass
|
82
|
-
subclass.const_set(:SeregaAttribute, attribute_class)
|
83
|
-
|
84
|
-
map_class = Class.new(self::SeregaMap)
|
85
|
-
map_class.serializer_class = subclass
|
86
|
-
subclass.const_set(:SeregaMap, map_class)
|
87
|
-
|
88
|
-
map_point_class = Class.new(self::SeregaMapPoint)
|
89
|
-
map_point_class.serializer_class = subclass
|
90
|
-
subclass.const_set(:SeregaMapPoint, map_point_class)
|
91
|
-
|
92
|
-
object_serializer_class = Class.new(self::SeregaObjectSerializer)
|
93
|
-
object_serializer_class.serializer_class = subclass
|
94
|
-
subclass.const_set(:SeregaObjectSerializer, object_serializer_class)
|
95
|
-
|
96
|
-
check_attribute_params_class = Class.new(self::CheckAttributeParams)
|
97
|
-
check_attribute_params_class.serializer_class = subclass
|
98
|
-
subclass.const_set(:CheckAttributeParams, check_attribute_params_class)
|
99
|
-
|
100
|
-
check_initiate_params_class = Class.new(self::CheckInitiateParams)
|
101
|
-
check_initiate_params_class.serializer_class = subclass
|
102
|
-
subclass.const_set(:CheckInitiateParams, check_initiate_params_class)
|
103
|
-
|
104
|
-
check_serialize_params_class = Class.new(self::CheckSerializeParams)
|
105
|
-
check_serialize_params_class.serializer_class = subclass
|
106
|
-
subclass.const_set(:CheckSerializeParams, check_serialize_params_class)
|
107
|
-
|
108
|
-
# Assign same attributes
|
109
|
-
attributes.each_value do |attr|
|
110
|
-
subclass.attribute(attr.name, **attr.opts, &attr.block)
|
111
|
-
end
|
112
|
-
|
113
|
-
super
|
114
|
-
end
|
115
|
-
|
116
73
|
#
|
117
74
|
# Enables plugin for current serializer
|
118
75
|
#
|
@@ -170,6 +127,9 @@ class Serega
|
|
170
127
|
#
|
171
128
|
# Adds attribute
|
172
129
|
#
|
130
|
+
# Patched in:
|
131
|
+
# - plugin :presenter (additionally adds method in Presenter class)
|
132
|
+
#
|
173
133
|
# @param name [Symbol] Attribute name. Attribute value will be found by executing `object.<name>`
|
174
134
|
# @param opts [Hash] Options to serialize attribute
|
175
135
|
# @param block [Proc] Custom block to find attribute value. Accepts object and context.
|
@@ -250,6 +210,54 @@ class Serega
|
|
250
210
|
def as_json(object, opts = nil)
|
251
211
|
config.from_json.call(to_json(object, opts))
|
252
212
|
end
|
213
|
+
|
214
|
+
private
|
215
|
+
|
216
|
+
# Patched in:
|
217
|
+
# - plugin :batch (defines SeregaBatchLoaders, SeregaBatchLoader)
|
218
|
+
# - plugin :metadata (defines MetaAttribute and copies meta_attributes to subclasses)
|
219
|
+
# - plugin :presenter (defines Presenter)
|
220
|
+
def inherited(subclass)
|
221
|
+
config_class = Class.new(self::SeregaConfig)
|
222
|
+
config_class.serializer_class = subclass
|
223
|
+
subclass.const_set(:SeregaConfig, config_class)
|
224
|
+
subclass.instance_variable_set(:@config, subclass::SeregaConfig.new(config.opts))
|
225
|
+
|
226
|
+
attribute_class = Class.new(self::SeregaAttribute)
|
227
|
+
attribute_class.serializer_class = subclass
|
228
|
+
subclass.const_set(:SeregaAttribute, attribute_class)
|
229
|
+
|
230
|
+
map_class = Class.new(self::SeregaMap)
|
231
|
+
map_class.serializer_class = subclass
|
232
|
+
subclass.const_set(:SeregaMap, map_class)
|
233
|
+
|
234
|
+
map_point_class = Class.new(self::SeregaMapPoint)
|
235
|
+
map_point_class.serializer_class = subclass
|
236
|
+
subclass.const_set(:SeregaMapPoint, map_point_class)
|
237
|
+
|
238
|
+
object_serializer_class = Class.new(self::SeregaObjectSerializer)
|
239
|
+
object_serializer_class.serializer_class = subclass
|
240
|
+
subclass.const_set(:SeregaObjectSerializer, object_serializer_class)
|
241
|
+
|
242
|
+
check_attribute_params_class = Class.new(self::CheckAttributeParams)
|
243
|
+
check_attribute_params_class.serializer_class = subclass
|
244
|
+
subclass.const_set(:CheckAttributeParams, check_attribute_params_class)
|
245
|
+
|
246
|
+
check_initiate_params_class = Class.new(self::CheckInitiateParams)
|
247
|
+
check_initiate_params_class.serializer_class = subclass
|
248
|
+
subclass.const_set(:CheckInitiateParams, check_initiate_params_class)
|
249
|
+
|
250
|
+
check_serialize_params_class = Class.new(self::CheckSerializeParams)
|
251
|
+
check_serialize_params_class.serializer_class = subclass
|
252
|
+
subclass.const_set(:CheckSerializeParams, check_serialize_params_class)
|
253
|
+
|
254
|
+
# Assign same attributes
|
255
|
+
attributes.each_value do |attr|
|
256
|
+
subclass.attribute(attr.name, **attr.opts, &attr.block)
|
257
|
+
end
|
258
|
+
|
259
|
+
super
|
260
|
+
end
|
253
261
|
end
|
254
262
|
|
255
263
|
#
|
@@ -266,7 +274,7 @@ class Serega
|
|
266
274
|
# @option opts [Boolean] :validate Validates provided modifiers (Default is true)
|
267
275
|
#
|
268
276
|
def initialize(opts = nil)
|
269
|
-
@opts = (opts.nil? || opts.empty?) ? FROZEN_EMPTY_HASH :
|
277
|
+
@opts = (opts.nil? || opts.empty?) ? FROZEN_EMPTY_HASH : parse_modifiers(opts)
|
270
278
|
self.class::CheckInitiateParams.new(@opts).validate if opts&.fetch(:check_initiate_params) { config.check_initiate_params }
|
271
279
|
end
|
272
280
|
|
@@ -340,13 +348,29 @@ class Serega
|
|
340
348
|
self.class.config
|
341
349
|
end
|
342
350
|
|
343
|
-
def
|
344
|
-
|
345
|
-
|
346
|
-
|
351
|
+
def parse_modifiers(opts)
|
352
|
+
result = {}
|
353
|
+
|
354
|
+
opts.each do |key, value|
|
355
|
+
value = parse_modifier(value) if (key == :only) || (key == :except) || (key == :with)
|
356
|
+
result[key] = value
|
347
357
|
end
|
358
|
+
|
359
|
+
result
|
360
|
+
end
|
361
|
+
|
362
|
+
# Patched in:
|
363
|
+
# - plugin :string_modifiers (parses string modifiers differently)
|
364
|
+
def parse_modifier(value)
|
365
|
+
SeregaUtils::ToHash.call(value)
|
348
366
|
end
|
349
367
|
|
368
|
+
# Patched in:
|
369
|
+
# - plugin :activerecord_preloads (loads defined :preloads to object)
|
370
|
+
# - plugin :batch (runs serialization of collected batches)
|
371
|
+
# - plugin :root (wraps result `{ root => result }`)
|
372
|
+
# - plugin :context_metadata (adds context metadata to final result)
|
373
|
+
# - plugin :metadata (adds metadata to final result)
|
350
374
|
def serialize(object, opts)
|
351
375
|
self.class::SeregaObjectSerializer
|
352
376
|
.new(**opts, points: map)
|
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.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrey Glushkov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-03-27 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
JSON Serializer
|
@@ -53,7 +53,11 @@ files:
|
|
53
53
|
- lib/serega/plugins/batch/lib/validations/check_opt_batch.rb
|
54
54
|
- lib/serega/plugins/context_metadata/context_metadata.rb
|
55
55
|
- lib/serega/plugins/formatters/formatters.rb
|
56
|
-
- lib/serega/plugins/
|
56
|
+
- lib/serega/plugins/if/if.rb
|
57
|
+
- lib/serega/plugins/if/validations/check_opt_if.rb
|
58
|
+
- lib/serega/plugins/if/validations/check_opt_if_value.rb
|
59
|
+
- lib/serega/plugins/if/validations/check_opt_unless.rb
|
60
|
+
- lib/serega/plugins/if/validations/check_opt_unless_value.rb
|
57
61
|
- lib/serega/plugins/metadata/meta_attribute.rb
|
58
62
|
- lib/serega/plugins/metadata/metadata.rb
|
59
63
|
- lib/serega/plugins/metadata/validations/check_block.rb
|
@@ -115,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
115
119
|
- !ruby/object:Gem::Version
|
116
120
|
version: '0'
|
117
121
|
requirements: []
|
118
|
-
rubygems_version: 3.4.
|
122
|
+
rubygems_version: 3.4.7
|
119
123
|
signing_key:
|
120
124
|
specification_version: 4
|
121
125
|
summary: JSON Serializer
|