serega 0.20.1 → 0.21.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 +3 -0
- data/VERSION +1 -1
- data/lib/serega/plugins/activerecord_preloads/activerecord_preloads.rb +17 -10
- data/lib/serega/plugins/string_modifiers/parse_string_modifiers.rb +43 -30
- data/lib/serega.rb +12 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ea0f19662815497e76a3ace9b247e90268f7c44a3cf917b97a186887043fc7b
|
4
|
+
data.tar.gz: fb13ebbaa26603c0eda053e78634aaecf1a8d040c73b5824892b03c2b0d2a70d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a5847251f29dfd44a7da2cd9b5a99411aa430323d1d57e7706e176cc234f96ff7575298c5909c753aa4f3a2895d41a48c3c6a5b67a95e0bdac935f38c5c6f15d
|
7
|
+
data.tar.gz: 4fdf12f075816ea3ba155ace47b6f5e6c7b3b0bcd000179e43e4edf356e63b19360de227b6112b4fe98e310975da4afebc3d5c86476deadc749c4197330ddfd0
|
data/README.md
CHANGED
@@ -549,6 +549,9 @@ UserSerializer.to_h(user)
|
|
549
549
|
# => preloads {users_stats: {}, albums: { downloads: {} }}
|
550
550
|
```
|
551
551
|
|
552
|
+
For testing purposes preloading can be done manually with
|
553
|
+
`#preload_association_to(obj)` instance method
|
554
|
+
|
552
555
|
### Plugin :batch
|
553
556
|
|
554
557
|
Helps to omit N+1.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.21.0
|
@@ -90,6 +90,22 @@ class Serega
|
|
90
90
|
# Overrides Serega class instance methods
|
91
91
|
#
|
92
92
|
module InstanceMethods
|
93
|
+
#
|
94
|
+
# Preloads associations to object
|
95
|
+
#
|
96
|
+
# @param object [Object] Any object
|
97
|
+
# @return provided object
|
98
|
+
#
|
99
|
+
def preload_associations_to(object)
|
100
|
+
return object if object.nil? || (object.is_a?(Array) && object.empty?)
|
101
|
+
|
102
|
+
preloads = preloads() # `preloads()` method comes from :preloads plugin
|
103
|
+
return object if preloads.empty?
|
104
|
+
|
105
|
+
Preloader.preload(object, preloads)
|
106
|
+
object
|
107
|
+
end
|
108
|
+
|
93
109
|
private
|
94
110
|
|
95
111
|
#
|
@@ -97,18 +113,9 @@ class Serega
|
|
97
113
|
# Preloads associations to object before serialization
|
98
114
|
#
|
99
115
|
def serialize(object, _opts)
|
100
|
-
|
116
|
+
preload_associations_to(object)
|
101
117
|
super
|
102
118
|
end
|
103
|
-
|
104
|
-
def add_preloads(obj)
|
105
|
-
return obj if obj.nil? || (obj.is_a?(Array) && obj.empty?)
|
106
|
-
|
107
|
-
preloads = preloads() # `preloads()` method comes from :preloads plugin
|
108
|
-
return obj if preloads.empty?
|
109
|
-
|
110
|
-
Preloader.preload(obj, preloads)
|
111
|
-
end
|
112
119
|
end
|
113
120
|
end
|
114
121
|
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "stringio"
|
4
|
-
|
5
3
|
class Serega
|
6
4
|
module SeregaPlugins
|
7
5
|
#
|
@@ -25,6 +23,14 @@ class Serega
|
|
25
23
|
# Modifiers parser
|
26
24
|
#
|
27
25
|
class ParseStringModifiers
|
26
|
+
COMMA = ","
|
27
|
+
COMMA_CODEPOINT = COMMA.ord
|
28
|
+
LPAREN = "("
|
29
|
+
LPAREN_CODEPOINT = LPAREN.ord
|
30
|
+
RPAREN = ")"
|
31
|
+
RPAREN_CODEPOINT = RPAREN.ord
|
32
|
+
private_constant :COMMA, :LPAREN, :RPAREN, :COMMA_CODEPOINT, :LPAREN_CODEPOINT, :RPAREN_CODEPOINT
|
33
|
+
|
28
34
|
class << self
|
29
35
|
#
|
30
36
|
# Parses string modifiers
|
@@ -40,45 +46,52 @@ class Serega
|
|
40
46
|
# parse("user,comments") => { user: {}, comments: {} }
|
41
47
|
# parse("user(comments(text))") => { user: { comments: { text: {} } } }
|
42
48
|
def parse(fields)
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
path_stack = nil
|
47
|
-
fields = StringIO.new(fields)
|
49
|
+
result = {}
|
50
|
+
attribute_storage = result
|
51
|
+
path_stack = (fields.include?(LPAREN) || fields.include?(RPAREN)) ? [] : nil
|
48
52
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
when
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
53
|
+
start_index = 0
|
54
|
+
end_index = 0
|
55
|
+
fields.each_codepoint do |codepoint|
|
56
|
+
case codepoint
|
57
|
+
when COMMA_CODEPOINT
|
58
|
+
attribute = extract_attribute(fields, start_index, end_index)
|
59
|
+
add_attribute(attribute_storage, attribute, FROZEN_EMPTY_HASH) if attribute
|
60
|
+
start_index = end_index + 1
|
61
|
+
when LPAREN_CODEPOINT
|
62
|
+
attribute = extract_attribute(fields, start_index, end_index)
|
63
|
+
if attribute
|
64
|
+
attribute_storage = add_attribute(attribute_storage, attribute, {})
|
65
|
+
path_stack.push(attribute)
|
66
|
+
end
|
67
|
+
start_index = end_index + 1
|
68
|
+
when RPAREN_CODEPOINT
|
69
|
+
attribute = extract_attribute(fields, start_index, end_index)
|
70
|
+
add_attribute(attribute_storage, attribute, FROZEN_EMPTY_HASH) if attribute
|
71
|
+
path_stack.pop
|
72
|
+
attribute_storage = dig?(result, path_stack)
|
73
|
+
start_index = end_index + 1
|
61
74
|
end
|
75
|
+
|
76
|
+
end_index += 1
|
62
77
|
end
|
63
78
|
|
64
|
-
|
79
|
+
attribute = extract_attribute(fields, start_index, end_index)
|
80
|
+
add_attribute(attribute_storage, attribute, FROZEN_EMPTY_HASH) if attribute
|
65
81
|
|
66
|
-
|
82
|
+
result
|
67
83
|
end
|
68
84
|
|
69
85
|
private
|
70
86
|
|
71
|
-
def
|
87
|
+
def extract_attribute(fields, start_index, end_index)
|
88
|
+
attribute = fields[start_index, end_index - start_index]
|
72
89
|
attribute.strip!
|
73
|
-
|
74
|
-
|
75
|
-
name = attribute.to_sym
|
76
|
-
attribute.clear
|
77
|
-
|
78
|
-
current_attrs = dig?(res, path_stack)
|
79
|
-
current_attrs[name] = nested_attributes
|
90
|
+
attribute.empty? ? nil : attribute.to_sym
|
91
|
+
end
|
80
92
|
|
81
|
-
|
93
|
+
def add_attribute(storage, attribute, nested_attributes = FROZEN_EMPTY_HASH)
|
94
|
+
storage[attribute] = nested_attributes
|
82
95
|
end
|
83
96
|
|
84
97
|
def dig?(hash, path)
|
data/lib/serega.rb
CHANGED
@@ -167,6 +167,7 @@ class Serega
|
|
167
167
|
modifiers_opts = FROZEN_EMPTY_HASH
|
168
168
|
serialize_opts = nil
|
169
169
|
else
|
170
|
+
opts.transform_keys!(&:to_sym)
|
170
171
|
serialize_opts = opts.except(*initiate_keys)
|
171
172
|
modifiers_opts = opts.slice(*initiate_keys)
|
172
173
|
end
|
@@ -296,7 +297,14 @@ class Serega
|
|
296
297
|
# @option opts [Boolean] :validate Validates provided modifiers (Default is true)
|
297
298
|
#
|
298
299
|
def initialize(opts = nil)
|
299
|
-
@opts =
|
300
|
+
@opts =
|
301
|
+
if opts.nil? || opts.empty?
|
302
|
+
FROZEN_EMPTY_HASH
|
303
|
+
else
|
304
|
+
opts.transform_keys!(&:to_sym)
|
305
|
+
parse_modifiers(opts)
|
306
|
+
end
|
307
|
+
|
300
308
|
self.class::CheckInitiateParams.new(@opts).validate if opts&.fetch(:check_initiate_params) { config.check_initiate_params }
|
301
309
|
|
302
310
|
@plan = self.class::SeregaPlan.call(@opts)
|
@@ -320,10 +328,10 @@ class Serega
|
|
320
328
|
# @return [Hash] Serialization result
|
321
329
|
#
|
322
330
|
def call(object, opts = nil)
|
323
|
-
|
324
|
-
opts
|
325
|
-
opts[:context] ||= {}
|
331
|
+
opts = opts ? opts.transform_keys!(&:to_sym) : {}
|
332
|
+
self.class::CheckSerializeParams.new(opts).validate unless opts.empty?
|
326
333
|
|
334
|
+
opts[:context] ||= {}
|
327
335
|
serialize(object, opts)
|
328
336
|
end
|
329
337
|
|
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.21.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: 2024-
|
11
|
+
date: 2024-11-18 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
JSON Serializer
|