ree_lib 1.0.54 → 1.0.56
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/Gemfile.lock +3 -1
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/association.rb +100 -103
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/associations.rb +54 -51
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/dataset_extensions.rb +20 -20
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/functions/load_agg.rb +9 -3
- data/lib/ree_lib/packages/ree_dao/schemas/ree_dao/functions/load_agg.schema.json +6 -6
- data/lib/ree_lib/packages/ree_dao/spec/ree_dao/functions/load_agg/load_agg_spec.rb +126 -20
- data/lib/ree_lib/packages/ree_dao/spec/ree_dao/functions/load_agg/ree_dao_load_agg_test.rb +76 -45
- data/lib/ree_lib/version.rb +1 -1
- 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: 23c4603ab3ab820869ca4478b42b3d350c5484c8da7b21c99b469449f45764a1
|
4
|
+
data.tar.gz: 4293f4d083185f09f6098e11698b5f35981a748b00ff84e486389bab19445751
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe885988996c1f0b9aeba40c9f61e119ab4ffc02aa471afe3774b470192fc5601093c1b13673febebad76bf348baa0be61cb2e19a5abf81b1970b518d86ddc9d
|
7
|
+
data.tar.gz: acbdf84eacfa6c46c6997999af1e0eb5dc03eedc95b95d954927a3907048c9c28d924328041203d02db1bd5c9dc78310c2cc234db826c74e585a8701b7982ed9
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ree_lib (1.0.
|
4
|
+
ree_lib (1.0.56)
|
5
5
|
binding_of_caller (~> 1.0.0)
|
6
6
|
i18n (~> 1.12.0)
|
7
7
|
loofah (~> 2.18.0)
|
@@ -38,6 +38,8 @@ GEM
|
|
38
38
|
crass (~> 1.0.2)
|
39
39
|
nokogiri (>= 1.5.9)
|
40
40
|
msgpack (1.6.0)
|
41
|
+
nokogiri (1.15.3-x86_64-darwin)
|
42
|
+
racc (~> 1.4)
|
41
43
|
nokogiri (1.15.3-x86_64-linux)
|
42
44
|
racc (~> 1.4)
|
43
45
|
oj (3.13.23)
|
@@ -26,8 +26,12 @@ module ReeDao
|
|
26
26
|
load_association(assoc_type, assoc_name, **opts, &block)
|
27
27
|
end
|
28
28
|
|
29
|
+
def handle_field(assoc_name, proc)
|
30
|
+
proc.call
|
31
|
+
end
|
32
|
+
|
29
33
|
contract(
|
30
|
-
Or[:belongs_to, :has_one, :has_many
|
34
|
+
Or[:belongs_to, :has_one, :has_many],
|
31
35
|
Symbol,
|
32
36
|
Ksplat[RestKeys => Any],
|
33
37
|
Optblock => Nilor[Array]
|
@@ -56,6 +60,7 @@ module ReeDao
|
|
56
60
|
assoc_name,
|
57
61
|
list,
|
58
62
|
scope: opts[:scope],
|
63
|
+
primary_key: opts[:primary_key],
|
59
64
|
foreign_key: opts[:foreign_key],
|
60
65
|
setter: opts[:setter],
|
61
66
|
reverse: false
|
@@ -65,6 +70,7 @@ module ReeDao
|
|
65
70
|
assoc_name,
|
66
71
|
list,
|
67
72
|
scope: opts[:scope],
|
73
|
+
primary_key: opts[:primary_key],
|
68
74
|
foreign_key: opts[:foreign_key],
|
69
75
|
setter: opts[:setter],
|
70
76
|
reverse: true
|
@@ -74,6 +80,7 @@ module ReeDao
|
|
74
80
|
assoc_name,
|
75
81
|
list,
|
76
82
|
scope: opts[:scope],
|
83
|
+
primary_key: opts[:primary_key],
|
77
84
|
foreign_key: opts[:foreign_key],
|
78
85
|
setter: opts[:setter]
|
79
86
|
)
|
@@ -82,16 +89,16 @@ module ReeDao
|
|
82
89
|
assoc_name,
|
83
90
|
list,
|
84
91
|
scope: opts[:scope],
|
92
|
+
primary_key: opts[:primary_key],
|
85
93
|
foreign_key: opts[:foreign_key],
|
86
|
-
setter: opts[:setter]
|
87
|
-
skip_dao: true
|
94
|
+
setter: opts[:setter]
|
88
95
|
)
|
89
96
|
end
|
90
97
|
end
|
91
98
|
|
92
|
-
contract(Hash, Bool, Block => Any)
|
99
|
+
contract(Or[Hash, Array], Bool, Block => Any)
|
93
100
|
def process_block(assoc, autoload_children, &block)
|
94
|
-
assoc_list = assoc.values.flatten
|
101
|
+
assoc_list = assoc.is_a?(Array) ? assoc : assoc.values.flatten
|
95
102
|
|
96
103
|
if ReeDao::Associations.sync_mode?
|
97
104
|
ReeDao::Associations.new(
|
@@ -108,7 +115,7 @@ module ReeDao
|
|
108
115
|
parent.local_vars,
|
109
116
|
autoload_children,
|
110
117
|
**global_opts
|
111
|
-
).instance_exec(assoc_list, &block).map(&:join)
|
118
|
+
).instance_exec(assoc_list, &block)[:association_threads].map(&:join)
|
112
119
|
end
|
113
120
|
end
|
114
121
|
|
@@ -116,59 +123,66 @@ module ReeDao
|
|
116
123
|
Symbol,
|
117
124
|
Array,
|
118
125
|
Kwargs[
|
126
|
+
primary_key: Nilor[Symbol],
|
119
127
|
foreign_key: Nilor[Symbol],
|
120
|
-
scope: Nilor[Sequel::Dataset],
|
128
|
+
scope: Nilor[Sequel::Dataset, Array],
|
121
129
|
setter: Nilor[Or[Symbol, Proc]],
|
122
130
|
reverse: Bool
|
123
|
-
] => Hash
|
124
|
-
)
|
125
|
-
def one_to_one(
|
126
|
-
assoc_name,
|
127
|
-
list,
|
128
|
-
scope: nil,
|
129
|
-
foreign_key: nil,
|
130
|
-
setter: nil,
|
131
|
-
reverse: true
|
131
|
+
] => Or[Hash, Array]
|
132
132
|
)
|
133
|
+
def one_to_one(assoc_name, list, scope: nil, primary_key: :id, foreign_key: nil, setter: nil, reverse: true)
|
133
134
|
return {} if list.empty?
|
134
135
|
|
135
|
-
|
136
|
-
|
137
|
-
if reverse
|
138
|
-
if !foreign_key
|
139
|
-
name = underscore(demodulize(list.first.class.name))
|
140
|
-
foreign_key = "#{name}_id".to_sym
|
141
|
-
end
|
136
|
+
primary_key ||= :id
|
142
137
|
|
143
|
-
|
138
|
+
if scope.is_a?(Array)
|
139
|
+
items = scope
|
144
140
|
else
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
141
|
+
assoc_dao = find_dao(assoc_name, parent, scope)
|
142
|
+
|
143
|
+
if reverse
|
144
|
+
if !foreign_key
|
145
|
+
name = underscore(demodulize(list.first.class.name))
|
146
|
+
foreign_key = "#{name}_id".to_sym
|
147
|
+
end
|
149
148
|
|
150
|
-
|
151
|
-
|
152
|
-
root_ids = list.map(&:"#{"#{name}_id".to_sym}").uniq
|
153
|
-
foreign_key = :id
|
149
|
+
root_ids = list.map(&:id).uniq
|
154
150
|
else
|
155
|
-
|
156
|
-
|
151
|
+
if !foreign_key
|
152
|
+
dto_class = assoc_dao
|
153
|
+
.opts[:schema_mapper]
|
154
|
+
.dto(:db_load)
|
155
|
+
|
156
|
+
name = underscore(demodulize(dto_class.name))
|
157
|
+
|
158
|
+
root_ids = list.map(&:"#{"#{name}_id".to_sym}").uniq
|
159
|
+
foreign_key = :id
|
160
|
+
else
|
161
|
+
root_ids = list.map(&:"#{foreign_key}")
|
162
|
+
foreign_key = :id
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
default_scope = if !scope
|
167
|
+
assoc_dao&.where(foreign_key => root_ids)
|
157
168
|
end
|
169
|
+
|
170
|
+
items = add_scopes(default_scope, scope, global_opts[assoc_name])
|
158
171
|
end
|
159
172
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
173
|
+
assoc = if foreign_key
|
174
|
+
index_by(items) { _1.send(foreign_key) }
|
175
|
+
else
|
176
|
+
items
|
177
|
+
end
|
165
178
|
|
166
179
|
populate_association(
|
167
180
|
list,
|
168
181
|
assoc,
|
169
182
|
assoc_name,
|
170
183
|
setter: setter,
|
171
|
-
reverse: reverse
|
184
|
+
reverse: reverse,
|
185
|
+
primary_key: primary_key
|
172
186
|
)
|
173
187
|
|
174
188
|
assoc
|
@@ -179,39 +193,45 @@ module ReeDao
|
|
179
193
|
Array,
|
180
194
|
Kwargs[
|
181
195
|
foreign_key: Nilor[Symbol],
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
] => Hash
|
186
|
-
)
|
187
|
-
def one_to_many(
|
188
|
-
assoc_name,
|
189
|
-
list,
|
190
|
-
foreign_key: nil,
|
191
|
-
scope: nil,
|
192
|
-
setter: nil,
|
193
|
-
skip_dao: false
|
196
|
+
primary_key: Nilor[Symbol],
|
197
|
+
scope: Nilor[Sequel::Dataset, Array],
|
198
|
+
setter: Nilor[Or[Symbol, Proc]]
|
199
|
+
] => Or[Hash, Array]
|
194
200
|
)
|
201
|
+
def one_to_many(assoc_name, list, primary_key: nil, foreign_key: nil, scope: nil, setter: nil)
|
195
202
|
return {} if list.empty?
|
196
203
|
|
197
|
-
|
198
|
-
assoc_dao = find_dao(assoc_name, parent, scope) if !skip_dao
|
204
|
+
primary_key ||= :id
|
199
205
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
206
|
+
if scope.is_a?(Array)
|
207
|
+
items = scope
|
208
|
+
else
|
209
|
+
assoc_dao = nil
|
210
|
+
assoc_dao = find_dao(assoc_name, parent, scope)
|
211
|
+
|
212
|
+
foreign_key ||= "#{underscore(demodulize(list.first.class.name))}_id".to_sym
|
213
|
+
|
214
|
+
root_ids = list.map(&:"#{primary_key}")
|
215
|
+
|
216
|
+
default_scope = if !scope
|
217
|
+
assoc_dao&.where(foreign_key => root_ids)
|
218
|
+
end
|
219
|
+
|
220
|
+
items = add_scopes(default_scope, scope, global_opts[assoc_name])
|
221
|
+
end
|
207
222
|
|
208
|
-
assoc =
|
223
|
+
assoc = if foreign_key
|
224
|
+
group_by(items) { _1.send(foreign_key) }
|
225
|
+
else
|
226
|
+
items
|
227
|
+
end
|
209
228
|
|
210
229
|
populate_association(
|
211
230
|
list,
|
212
231
|
assoc,
|
213
232
|
assoc_name,
|
214
|
-
setter: setter
|
233
|
+
setter: setter,
|
234
|
+
primary_key: primary_key
|
215
235
|
)
|
216
236
|
|
217
237
|
assoc
|
@@ -219,20 +239,15 @@ module ReeDao
|
|
219
239
|
|
220
240
|
contract(
|
221
241
|
Array,
|
222
|
-
Hash,
|
242
|
+
Or[Hash, Array],
|
223
243
|
Symbol,
|
224
244
|
Kwargs[
|
245
|
+
primary_key: Nilor[Symbol],
|
225
246
|
reverse: Nilor[Bool],
|
226
247
|
setter: Nilor[Or[Symbol, Proc]]
|
227
248
|
] => Any
|
228
249
|
)
|
229
|
-
def populate_association(
|
230
|
-
list,
|
231
|
-
association_index,
|
232
|
-
assoc_name,
|
233
|
-
reverse: nil,
|
234
|
-
setter: nil
|
235
|
-
)
|
250
|
+
def populate_association(list, association_index, assoc_name, primary_key: nil, reverse: nil, setter: nil)
|
236
251
|
assoc_setter = if setter
|
237
252
|
setter
|
238
253
|
else
|
@@ -244,37 +259,25 @@ module ReeDao
|
|
244
259
|
self.instance_exec(item, association_index, &assoc_setter)
|
245
260
|
else
|
246
261
|
key = if reverse.nil?
|
247
|
-
|
262
|
+
primary_key
|
248
263
|
else
|
249
|
-
reverse ?
|
264
|
+
reverse ? primary_key : "#{assoc_name}_id"
|
250
265
|
end
|
251
266
|
value = association_index[item.send(key)]
|
252
267
|
next if value.nil?
|
253
268
|
|
254
|
-
|
269
|
+
begin
|
270
|
+
item.send(assoc_setter, value)
|
271
|
+
rescue NoMethodError
|
272
|
+
item.send("#{assoc_name}=", value)
|
273
|
+
end
|
255
274
|
end
|
256
275
|
end
|
257
276
|
end
|
258
277
|
|
259
278
|
contract(Nilor[Sequel::Dataset], Nilor[Sequel::Dataset], Nilor[Proc] => Array)
|
260
279
|
def add_scopes(default_scope, scope, named_scope)
|
261
|
-
|
262
|
-
res = default_scope
|
263
|
-
end
|
264
|
-
|
265
|
-
if default_scope && scope
|
266
|
-
if scope == []
|
267
|
-
res = default_scope
|
268
|
-
else
|
269
|
-
res = merge_scopes(default_scope, scope)
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
if !default_scope && scope
|
274
|
-
return [] if scope.empty?
|
275
|
-
|
276
|
-
res = scope
|
277
|
-
end
|
280
|
+
res = scope || default_scope
|
278
281
|
|
279
282
|
if named_scope
|
280
283
|
res = named_scope.call(res)
|
@@ -283,18 +286,6 @@ module ReeDao
|
|
283
286
|
res.all
|
284
287
|
end
|
285
288
|
|
286
|
-
def merge_scopes(s1, s2)
|
287
|
-
if s2.opts[:where]
|
288
|
-
s1 = s1.where(s2.opts[:where])
|
289
|
-
end
|
290
|
-
|
291
|
-
if s2.opts[:order]
|
292
|
-
s1 = s1.order(*s2.opts[:order])
|
293
|
-
end
|
294
|
-
|
295
|
-
s1
|
296
|
-
end
|
297
|
-
|
298
289
|
def find_dao(assoc_name, parent, scope)
|
299
290
|
dao_from_name = parent.instance_variable_get("@#{assoc_name}") || parent.instance_variable_get("@#{assoc_name}s")
|
300
291
|
return dao_from_name if dao_from_name
|
@@ -307,5 +298,11 @@ module ReeDao
|
|
307
298
|
|
308
299
|
raise ArgumentError, "can't find DAO for :#{assoc_name}, provide correct scope or association name"
|
309
300
|
end
|
301
|
+
|
302
|
+
def method_missing(method, *args, &block)
|
303
|
+
return super if !parent.agg_caller.private_methods(false).include?(method)
|
304
|
+
|
305
|
+
parent.agg_caller.send(method, *args, &block)
|
306
|
+
end
|
310
307
|
end
|
311
308
|
end
|
@@ -8,14 +8,19 @@ module ReeDao
|
|
8
8
|
@agg_caller = agg_caller
|
9
9
|
@list = list
|
10
10
|
@local_vars = local_vars
|
11
|
-
@
|
12
|
-
@global_opts = opts
|
11
|
+
@global_opts = opts || {}
|
13
12
|
@only = opts[:only] if opts[:only]
|
14
13
|
@except = opts[:except] if opts[:except]
|
15
14
|
@autoload_children = autoload_children
|
16
15
|
|
17
16
|
raise ArgumentError.new("you can't use both :only and :except arguments at the same time") if @only && @except
|
18
17
|
|
18
|
+
|
19
|
+
if !self.class.sync_mode?
|
20
|
+
@assoc_threads = []
|
21
|
+
@field_threads = []
|
22
|
+
end
|
23
|
+
|
19
24
|
local_vars.each do |k, v|
|
20
25
|
instance_variable_set(k, v)
|
21
26
|
|
@@ -31,58 +36,34 @@ module ReeDao
|
|
31
36
|
|
32
37
|
contract(
|
33
38
|
Symbol,
|
34
|
-
|
35
|
-
scope?: Sequel::Dataset,
|
36
|
-
setter?: Or[Symbol, Proc],
|
37
|
-
foreign_key?: Symbol,
|
38
|
-
autoload_children?: Bool
|
39
|
-
],
|
39
|
+
Nilor[Proc, Sequel::Dataset],
|
40
40
|
Optblock => Any
|
41
41
|
)
|
42
|
-
def belongs_to(assoc_name,
|
43
|
-
association(__method__, assoc_name,
|
42
|
+
def belongs_to(assoc_name, opts = nil, &block)
|
43
|
+
association(__method__, assoc_name, opts, &block)
|
44
44
|
end
|
45
45
|
|
46
46
|
contract(
|
47
47
|
Symbol,
|
48
|
-
|
49
|
-
scope?: Sequel::Dataset,
|
50
|
-
setter?: Or[Symbol, Proc],
|
51
|
-
foreign_key?: Symbol,
|
52
|
-
autoload_children?: Bool
|
53
|
-
],
|
48
|
+
Nilor[Proc, Sequel::Dataset],
|
54
49
|
Optblock => Any
|
55
50
|
)
|
56
|
-
def has_one(assoc_name,
|
57
|
-
association(__method__, assoc_name,
|
51
|
+
def has_one(assoc_name, opts = nil, &block)
|
52
|
+
association(__method__, assoc_name, opts, &block)
|
58
53
|
end
|
59
54
|
|
60
55
|
contract(
|
61
56
|
Symbol,
|
62
|
-
|
63
|
-
scope?: Sequel::Dataset,
|
64
|
-
setter?: Or[Symbol, Proc],
|
65
|
-
foreign_key?: Symbol,
|
66
|
-
autoload_children?: Bool
|
67
|
-
],
|
57
|
+
Nilor[Proc, Sequel::Dataset],
|
68
58
|
Optblock => Any
|
69
59
|
)
|
70
|
-
def has_many(assoc_name,
|
71
|
-
association(__method__, assoc_name,
|
60
|
+
def has_many(assoc_name, opts = nil, &block)
|
61
|
+
association(__method__, assoc_name, opts, &block)
|
72
62
|
end
|
73
63
|
|
74
|
-
contract(
|
75
|
-
|
76
|
-
|
77
|
-
scope?: Sequel::Dataset,
|
78
|
-
setter?: Or[Symbol, Proc],
|
79
|
-
foreign_key?: Symbol,
|
80
|
-
autoload_children?: Bool
|
81
|
-
],
|
82
|
-
Optblock => Any
|
83
|
-
)
|
84
|
-
def field(assoc_name, **opts, &block)
|
85
|
-
association(__method__, assoc_name, **opts, &block)
|
64
|
+
contract(Symbol, Proc => Any)
|
65
|
+
def field(assoc_name, proc)
|
66
|
+
association(__method__, assoc_name, proc)
|
86
67
|
end
|
87
68
|
|
88
69
|
private
|
@@ -95,26 +76,40 @@ module ReeDao
|
|
95
76
|
:field
|
96
77
|
],
|
97
78
|
Symbol,
|
98
|
-
|
99
|
-
scope?: Sequel::Dataset,
|
100
|
-
setter?: Or[Symbol, Proc],
|
101
|
-
foreign_key?: Symbol,
|
102
|
-
autoload_children?: Bool
|
103
|
-
],
|
79
|
+
Nilor[Proc, Sequel::Dataset],
|
104
80
|
Optblock => Any
|
105
81
|
)
|
106
|
-
def association(assoc_type, assoc_name,
|
82
|
+
def association(assoc_type, assoc_name, opts, &block)
|
107
83
|
if self.class.sync_mode?
|
108
84
|
return if association_is_not_included?(assoc_name) || list.empty?
|
109
|
-
|
85
|
+
|
110
86
|
association = Association.new(self, list, **global_opts)
|
111
|
-
|
87
|
+
if assoc_type == :field
|
88
|
+
association.handle_field(assoc_name, opts)
|
89
|
+
else
|
90
|
+
association.load(assoc_type, assoc_name, **get_assoc_opts(opts), &block)
|
91
|
+
end
|
112
92
|
else
|
113
|
-
|
93
|
+
if association_is_not_included?(assoc_name) || list.empty?
|
94
|
+
return { association_threads: @assoc_threads, field_threads: @field_threads }
|
95
|
+
end
|
96
|
+
|
97
|
+
association = Association.new(self, list, **global_opts)
|
114
98
|
|
115
|
-
|
116
|
-
|
117
|
-
|
99
|
+
if assoc_type == :field
|
100
|
+
{
|
101
|
+
association_threads: @assoc_threads,
|
102
|
+
field_threads: @field_threads << Thread.new do
|
103
|
+
association.handle_field(assoc_name, opts)
|
104
|
+
end
|
105
|
+
}
|
106
|
+
else
|
107
|
+
{
|
108
|
+
association_threads: @assoc_threads << Thread.new do
|
109
|
+
association.load(assoc_type, assoc_name, **get_assoc_opts(opts), &block)
|
110
|
+
end,
|
111
|
+
field_threads: @field_threads
|
112
|
+
}
|
118
113
|
end
|
119
114
|
end
|
120
115
|
end
|
@@ -144,5 +139,13 @@ module ReeDao
|
|
144
139
|
|
145
140
|
agg_caller.send(method, *args, &block)
|
146
141
|
end
|
142
|
+
|
143
|
+
def get_assoc_opts(opts)
|
144
|
+
if opts.is_a?(Proc)
|
145
|
+
opts.call
|
146
|
+
else
|
147
|
+
{}
|
148
|
+
end
|
149
|
+
end
|
147
150
|
end
|
148
151
|
end
|
@@ -151,6 +151,26 @@ module ReeDao
|
|
151
151
|
for_update
|
152
152
|
end
|
153
153
|
|
154
|
+
def with_mapper(mapper)
|
155
|
+
clone(
|
156
|
+
schema_mapper: mapper || opts[:schema_mapper],
|
157
|
+
).with_row_proc(
|
158
|
+
Proc.new { |hash|
|
159
|
+
m = mapper || opts[:schema_mapper]
|
160
|
+
|
161
|
+
if m
|
162
|
+
entity = m.db_load(hash)
|
163
|
+
|
164
|
+
self.set_entity_cache(entity, hash)
|
165
|
+
|
166
|
+
entity
|
167
|
+
else
|
168
|
+
hash
|
169
|
+
end
|
170
|
+
}
|
171
|
+
)
|
172
|
+
end
|
173
|
+
|
154
174
|
private
|
155
175
|
|
156
176
|
def __ree_dao_cache
|
@@ -179,26 +199,6 @@ module ReeDao
|
|
179
199
|
end
|
180
200
|
end
|
181
201
|
|
182
|
-
def with_mapper(mapper)
|
183
|
-
clone(
|
184
|
-
schema_mapper: mapper || opts[:schema_mapper],
|
185
|
-
).with_row_proc(
|
186
|
-
Proc.new { |hash|
|
187
|
-
m = mapper || opts[:schema_mapper]
|
188
|
-
|
189
|
-
if m
|
190
|
-
entity = m.db_load(hash)
|
191
|
-
|
192
|
-
self.set_entity_cache(entity, hash)
|
193
|
-
|
194
|
-
entity
|
195
|
-
else
|
196
|
-
hash
|
197
|
-
end
|
198
|
-
}
|
199
|
-
)
|
200
|
-
end
|
201
|
-
|
202
202
|
def extract_primary_key(entity)
|
203
203
|
if primary_key.is_a?(Array)
|
204
204
|
primary_key.map do |key|
|
@@ -10,16 +10,17 @@ class ReeDao::LoadAgg
|
|
10
10
|
end
|
11
11
|
|
12
12
|
contract(
|
13
|
-
Or[Sequel::Dataset, ArrayOf[Integer], ArrayOf[EntityContract], Integer],
|
14
13
|
Nilor[DaoDatasetContract],
|
14
|
+
Or[Sequel::Dataset, ArrayOf[Integer], ArrayOf[EntityContract], Integer],
|
15
15
|
Ksplat[
|
16
16
|
only?: ArrayOf[Symbol],
|
17
17
|
except?: ArrayOf[Symbol],
|
18
|
+
to_dto?: Proc,
|
18
19
|
RestKeys => Any
|
19
20
|
],
|
20
21
|
Optblock => ArrayOf[Any]
|
21
22
|
)
|
22
|
-
def call(
|
23
|
+
def call(dao = nil, ids_or_scope, **opts, &block)
|
23
24
|
scope = if ids_or_scope.is_a?(Array) && ids_or_scope.any? { _1.is_a?(Integer) }
|
24
25
|
raise ArgumentError.new("Dao should be provided") if dao.nil?
|
25
26
|
return [] if ids_or_scope.empty?
|
@@ -35,6 +36,10 @@ class ReeDao::LoadAgg
|
|
35
36
|
|
36
37
|
list = scope.is_a?(Sequel::Dataset) ? scope.all : scope
|
37
38
|
|
39
|
+
if opts[:to_dto]
|
40
|
+
list = opts[:to_dto].call(list)
|
41
|
+
end
|
42
|
+
|
38
43
|
load_associations(list, **opts, &block) if block_given?
|
39
44
|
|
40
45
|
if ids_or_scope.is_a?(Array)
|
@@ -61,7 +66,8 @@ class ReeDao::LoadAgg
|
|
61
66
|
if ReeDao.load_sync_associations_enabled?
|
62
67
|
associations
|
63
68
|
else
|
64
|
-
associations.map(&:join)
|
69
|
+
associations[:association_threads].map(&:join)
|
70
|
+
associations[:field_threads].map(&:join)
|
65
71
|
end
|
66
72
|
end
|
67
73
|
end
|
@@ -14,20 +14,20 @@
|
|
14
14
|
],
|
15
15
|
"return": "ArrayOf[Any]",
|
16
16
|
"args": [
|
17
|
-
{
|
18
|
-
"arg": "ids_or_scope",
|
19
|
-
"arg_type": "req",
|
20
|
-
"type": "Or[Sequel::Dataset, ArrayOf[Integer], ArrayOf[PackageName::Entity], Integer]"
|
21
|
-
},
|
22
17
|
{
|
23
18
|
"arg": "dao",
|
24
19
|
"arg_type": "opt",
|
25
20
|
"type": "Nilor[PackageName::DaoName::Dao: \"SELECT * FROM `table`\"]"
|
26
21
|
},
|
22
|
+
{
|
23
|
+
"arg": "ids_or_scope",
|
24
|
+
"arg_type": "req",
|
25
|
+
"type": "Or[Sequel::Dataset, ArrayOf[Integer], ArrayOf[PackageName::Entity], Integer]"
|
26
|
+
},
|
27
27
|
{
|
28
28
|
"arg": "opts",
|
29
29
|
"arg_type": "keyrest",
|
30
|
-
"type": "Ksplat[:only? => ArrayOf[Symbol], :except? => ArrayOf[Symbol], \"RestKeys\" => Any]"
|
30
|
+
"type": "Ksplat[:only? => ArrayOf[Symbol], :except? => ArrayOf[Symbol], :to_dto? => Proc, \"RestKeys\" => Any]"
|
31
31
|
},
|
32
32
|
{
|
33
33
|
"arg": "block",
|
@@ -99,19 +99,67 @@ RSpec.describe :load_agg do
|
|
99
99
|
end
|
100
100
|
|
101
101
|
def call(ids_or_scope, **opts)
|
102
|
-
load_agg(
|
102
|
+
load_agg(users, ids_or_scope, **opts) do |users_list|
|
103
103
|
belongs_to :organization
|
104
|
-
has_many :books do
|
104
|
+
has_many :books do |books_list|
|
105
105
|
has_one :author
|
106
106
|
has_many :chapters
|
107
107
|
|
108
|
-
has_many :reviews do
|
108
|
+
has_many :reviews do |reviews_list|
|
109
109
|
has_one :review_author
|
110
|
+
|
111
|
+
field :review_calculatetable_field, -> { some_method(reviews_list) }
|
110
112
|
end
|
113
|
+
|
114
|
+
field :book_calculatetable_field, -> { change_book_titles(books_list) }
|
111
115
|
end
|
112
116
|
|
113
|
-
has_one :passport,
|
114
|
-
|
117
|
+
has_one :passport, -> { passport_opts }
|
118
|
+
has_one :custom_field, -> { custom_field_opts }
|
119
|
+
|
120
|
+
field :user_calculatetable_field, -> { some_method(users_list) }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def change_book_titles(books_list)
|
127
|
+
books_list.each do |book|
|
128
|
+
book.title = "#{book.title.upcase} changed"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def some_method(list)
|
133
|
+
puts list.map(&:id)
|
134
|
+
puts list.map { _1.class.name }
|
135
|
+
end
|
136
|
+
|
137
|
+
def passport_opts
|
138
|
+
{
|
139
|
+
foreign_key: :user_id,
|
140
|
+
scope: user_passports
|
141
|
+
}
|
142
|
+
end
|
143
|
+
|
144
|
+
def custom_field_opts
|
145
|
+
{
|
146
|
+
scope: books.where(title: "1984")
|
147
|
+
}
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
class ReeDaoLoadAggTest::UsersAggWithDto
|
152
|
+
include ReeDao::AggregateDSL
|
153
|
+
|
154
|
+
aggregate :users_agg_with_dto do
|
155
|
+
link :users, from: :ree_dao_load_agg_test
|
156
|
+
link :organizations, from: :ree_dao_load_agg_test
|
157
|
+
link :load_agg, from: :ree_dao
|
158
|
+
end
|
159
|
+
|
160
|
+
def call(ids_or_scope, **opts)
|
161
|
+
load_agg(users, ids_or_scope, **opts) do
|
162
|
+
belongs_to :organization
|
115
163
|
end
|
116
164
|
end
|
117
165
|
end
|
@@ -130,9 +178,9 @@ RSpec.describe :load_agg do
|
|
130
178
|
end
|
131
179
|
|
132
180
|
def call(ids_or_scope, **opts)
|
133
|
-
load_agg(
|
181
|
+
load_agg(users, ids_or_scope, **opts) do
|
134
182
|
belongs_to :organization
|
135
|
-
has_many :books,
|
183
|
+
has_many :books, -> { books_opts } do
|
136
184
|
has_one :author
|
137
185
|
has_many :chapters
|
138
186
|
|
@@ -142,6 +190,12 @@ RSpec.describe :load_agg do
|
|
142
190
|
end
|
143
191
|
end
|
144
192
|
end
|
193
|
+
|
194
|
+
private
|
195
|
+
|
196
|
+
def books_opts
|
197
|
+
{ autoload_children: true }
|
198
|
+
end
|
145
199
|
end
|
146
200
|
|
147
201
|
class ReeDaoLoadAggTest::UsersAggAutoloadReviewsChildren
|
@@ -158,18 +212,24 @@ RSpec.describe :load_agg do
|
|
158
212
|
end
|
159
213
|
|
160
214
|
def call(ids_or_scope, **opts)
|
161
|
-
load_agg(
|
215
|
+
load_agg(users, ids_or_scope, **opts) do
|
162
216
|
belongs_to :organization
|
163
217
|
has_many :books do
|
164
218
|
has_one :author
|
165
219
|
has_many :chapters
|
166
220
|
|
167
|
-
has_many :reviews, autoload_children: true do
|
221
|
+
has_many :reviews, -> { { autoload_children: true } } do
|
168
222
|
has_one :review_author
|
169
223
|
end
|
170
224
|
end
|
171
225
|
end
|
172
226
|
end
|
227
|
+
|
228
|
+
private
|
229
|
+
|
230
|
+
def reviews_opts
|
231
|
+
{ autoload_children: true }
|
232
|
+
end
|
173
233
|
end
|
174
234
|
|
175
235
|
class ReeDaoLoadAggTest::UsersAggBlockTest
|
@@ -183,13 +243,22 @@ RSpec.describe :load_agg do
|
|
183
243
|
end
|
184
244
|
|
185
245
|
def call(ids_or_scope, **opts)
|
186
|
-
load_agg(
|
246
|
+
load_agg(users, ids_or_scope, **opts) do
|
187
247
|
belongs_to :organization
|
188
|
-
has_many :books,
|
189
|
-
item.set_books([1337, 1337])
|
190
|
-
}
|
248
|
+
has_many :books, -> { books_opts }
|
191
249
|
end
|
192
250
|
end
|
251
|
+
|
252
|
+
private
|
253
|
+
|
254
|
+
def books_opts
|
255
|
+
{
|
256
|
+
setter: -> (item, items_index) {
|
257
|
+
b = items_index[item.id].each { |b| b.title = "Changed" }
|
258
|
+
item.set_books(b)
|
259
|
+
}
|
260
|
+
}
|
261
|
+
end
|
193
262
|
end
|
194
263
|
|
195
264
|
class ReeDaoLoadAggTest::UsersAggScopeMethodTest
|
@@ -203,17 +272,21 @@ RSpec.describe :load_agg do
|
|
203
272
|
end
|
204
273
|
|
205
274
|
def call(ids_or_scope, **opts)
|
206
|
-
load_agg(
|
275
|
+
load_agg(users, ids_or_scope, **opts) do |agg_list|
|
207
276
|
some_id = agg_list.first.id
|
208
277
|
title = "1984"
|
209
278
|
belongs_to :organization
|
210
279
|
|
211
|
-
has_many :books,
|
280
|
+
has_many :books, -> { books_opts(title) }
|
212
281
|
end
|
213
282
|
end
|
214
283
|
|
215
284
|
private
|
216
285
|
|
286
|
+
def books_opts(title)
|
287
|
+
{ scope: books_scope(title) }
|
288
|
+
end
|
289
|
+
|
217
290
|
def books_scope(title)
|
218
291
|
books.where(title: title)
|
219
292
|
end
|
@@ -230,7 +303,7 @@ RSpec.describe :load_agg do
|
|
230
303
|
end
|
231
304
|
|
232
305
|
def call(ids_or_scope, **opts)
|
233
|
-
load_agg(
|
306
|
+
load_agg(users, ids_or_scope, **opts) do
|
234
307
|
has_many :something
|
235
308
|
end
|
236
309
|
end
|
@@ -242,6 +315,7 @@ RSpec.describe :load_agg do
|
|
242
315
|
let(:users_agg_autoload_books_children) { ReeDaoLoadAggTest::UsersAggAutoloadBooksChildren.new }
|
243
316
|
let(:users_agg_autoload_reviews_children) { ReeDaoLoadAggTest::UsersAggAutoloadReviewsChildren.new }
|
244
317
|
let(:users_agg_without_dao) { ReeDaoLoadAggTest::UsersAggWithoutDao.new }
|
318
|
+
let(:users_agg_with_dto) { ReeDaoLoadAggTest::UsersAggWithDto.new }
|
245
319
|
let(:organizations) { ReeDaoLoadAggTest::Organizations.new }
|
246
320
|
let(:users) { ReeDaoLoadAggTest::Users.new }
|
247
321
|
let(:user_passports) { ReeDaoLoadAggTest::UserPassports.new }
|
@@ -266,6 +340,37 @@ RSpec.describe :load_agg do
|
|
266
340
|
}.to raise_error(ArgumentError)
|
267
341
|
}
|
268
342
|
|
343
|
+
it {
|
344
|
+
organizations.delete_all
|
345
|
+
users.delete_all
|
346
|
+
|
347
|
+
organization = ReeDaoLoadAggTest::Organization.new(name: "Test Org")
|
348
|
+
organizations.put(organization)
|
349
|
+
|
350
|
+
user_1 = ReeDaoLoadAggTest::User.new(name: "John", age: 33, organization_id: organization.id)
|
351
|
+
user_2 = ReeDaoLoadAggTest::User.new(name: "Sam", age: 21, organization_id: organization.id)
|
352
|
+
users.put(user_1)
|
353
|
+
users.put(user_2)
|
354
|
+
|
355
|
+
res = users_agg_with_dto.call(
|
356
|
+
users.all,
|
357
|
+
to_dto: -> (users) {
|
358
|
+
users.map do |user|
|
359
|
+
ReeDaoLoadAggTest::UserDto.new(
|
360
|
+
id: user.id,
|
361
|
+
name: user.name,
|
362
|
+
organization_id: user.organization_id,
|
363
|
+
full_name: user.name
|
364
|
+
)
|
365
|
+
end
|
366
|
+
}
|
367
|
+
)
|
368
|
+
|
369
|
+
res_user = res[0]
|
370
|
+
|
371
|
+
expect(res_user.class).to eq(ReeDaoLoadAggTest::UserDto)
|
372
|
+
}
|
373
|
+
|
269
374
|
it {
|
270
375
|
organizations.delete_all
|
271
376
|
users.delete_all
|
@@ -316,6 +421,7 @@ RSpec.describe :load_agg do
|
|
316
421
|
expect(res_user.passport).to eq(passport_1)
|
317
422
|
expect(res_user.passport.info).to eq("some info")
|
318
423
|
expect(res_user.books.count).to eq(2)
|
424
|
+
expect(res_user.books.map(&:title)).to eq(["1984 changed", "1408 changed"])
|
319
425
|
expect(res_user.books[0].author.name).to eq("George Orwell")
|
320
426
|
expect(res_user.books[0].chapters.map(&:title)).to eq(["beginning"])
|
321
427
|
expect(res_user.books[0].reviews[0].review_author.name).to eq("John Review")
|
@@ -540,7 +646,7 @@ RSpec.describe :load_agg do
|
|
540
646
|
res = users_agg_block.call(user_1.id)
|
541
647
|
|
542
648
|
u = res[0]
|
543
|
-
expect(u.books).to eq([
|
649
|
+
expect(u.books.map(&:title)).to eq(["Changed"])
|
544
650
|
}
|
545
651
|
|
546
652
|
it {
|
@@ -594,7 +700,7 @@ RSpec.describe :load_agg do
|
|
594
700
|
|
595
701
|
ids = [user_1, user_2].map(&:id)
|
596
702
|
|
597
|
-
res = load_agg(
|
703
|
+
res = load_agg(users, ids)
|
598
704
|
expect(res.count).to eq(2)
|
599
705
|
}
|
600
706
|
|
@@ -608,7 +714,7 @@ RSpec.describe :load_agg do
|
|
608
714
|
user_1 = ReeDaoLoadAggTest::User.new(name: "John", age: 33, organization_id: organization.id)
|
609
715
|
users.put(user_1)
|
610
716
|
|
611
|
-
res = load_agg(user_1.id
|
717
|
+
res = load_agg(users, user_1.id)
|
612
718
|
expect(res.count).to eq(1)
|
613
719
|
}
|
614
720
|
|
@@ -624,7 +730,7 @@ RSpec.describe :load_agg do
|
|
624
730
|
users.put(user_1)
|
625
731
|
users.put(user_2)
|
626
732
|
|
627
|
-
res = load_agg(users.where(organization_id: organization.id)
|
733
|
+
res = load_agg(users, users.where(organization_id: organization.id))
|
628
734
|
expect(res.count).to eq(2)
|
629
735
|
}
|
630
736
|
end
|
@@ -35,25 +35,45 @@ class ReeDaoLoadAggTest::Db
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
class ReeDaoLoadAggTest::
|
38
|
+
class ReeDaoLoadAggTest::Book
|
39
39
|
include ReeDto::EntityDSL
|
40
40
|
|
41
41
|
properties(
|
42
42
|
id: Nilor[Integer],
|
43
|
-
|
43
|
+
user_id: Integer,
|
44
|
+
title: Nilor[String]
|
44
45
|
)
|
45
46
|
|
46
|
-
def
|
47
|
-
@
|
47
|
+
def set_chapters(chapters)
|
48
|
+
@chapters = chapters; nil
|
48
49
|
end
|
49
50
|
|
50
|
-
def
|
51
|
-
@
|
51
|
+
def chapters
|
52
|
+
@chapters
|
52
53
|
end
|
53
54
|
|
54
|
-
|
55
|
-
|
55
|
+
def set_author(author)
|
56
|
+
@author = author
|
57
|
+
end
|
58
|
+
|
59
|
+
def author
|
60
|
+
@author
|
61
|
+
end
|
62
|
+
|
63
|
+
def set_reviews(reviews)
|
64
|
+
@reviews = reviews; nil
|
65
|
+
end
|
66
|
+
|
67
|
+
def reviews
|
68
|
+
@reviews
|
69
|
+
end
|
56
70
|
|
71
|
+
def title=(t)
|
72
|
+
@title = t
|
73
|
+
end
|
74
|
+
|
75
|
+
attr_accessor :title, :user_id
|
76
|
+
end
|
57
77
|
|
58
78
|
class ReeDaoLoadAggTest::User
|
59
79
|
include ReeDto::EntityDSL
|
@@ -81,10 +101,18 @@ class ReeDaoLoadAggTest::User
|
|
81
101
|
@passport
|
82
102
|
end
|
83
103
|
|
104
|
+
def books
|
105
|
+
@books
|
106
|
+
end
|
107
|
+
|
108
|
+
contract(ArrayOf[ReeDaoLoadAggTest::Book] => nil)
|
109
|
+
def set_books(books)
|
110
|
+
@books = books; nil
|
111
|
+
end
|
112
|
+
|
84
113
|
[
|
85
114
|
:organization,
|
86
115
|
:passport,
|
87
|
-
:books,
|
88
116
|
:movies,
|
89
117
|
:videogames,
|
90
118
|
:hobbies,
|
@@ -106,6 +134,45 @@ class ReeDaoLoadAggTest::User
|
|
106
134
|
attr_accessor :name, :age, :organization_id
|
107
135
|
end
|
108
136
|
|
137
|
+
class ReeDaoLoadAggTest::UserDto
|
138
|
+
include ReeDto::EntityDSL
|
139
|
+
|
140
|
+
properties(
|
141
|
+
id: Integer,
|
142
|
+
organization_id: Integer,
|
143
|
+
name: String,
|
144
|
+
full_name: String,
|
145
|
+
)
|
146
|
+
|
147
|
+
def set_organization(org)
|
148
|
+
@organization = org; nil
|
149
|
+
end
|
150
|
+
|
151
|
+
def organization
|
152
|
+
@organization
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
class ReeDaoLoadAggTest::Organization
|
157
|
+
include ReeDto::EntityDSL
|
158
|
+
|
159
|
+
properties(
|
160
|
+
id: Nilor[Integer],
|
161
|
+
name: String
|
162
|
+
)
|
163
|
+
|
164
|
+
contract(Array[ReeDaoLoadAggTest::User] => nil)
|
165
|
+
def set_users(users)
|
166
|
+
@users = users; nil
|
167
|
+
end
|
168
|
+
|
169
|
+
def users
|
170
|
+
@users ||= []
|
171
|
+
end
|
172
|
+
|
173
|
+
attr_accessor :name
|
174
|
+
end
|
175
|
+
|
109
176
|
|
110
177
|
class ReeDaoLoadAggTest::UserPassport
|
111
178
|
include ReeDto::EntityDSL
|
@@ -189,42 +256,6 @@ class ReeDaoLoadAggTest::Dream
|
|
189
256
|
)
|
190
257
|
end
|
191
258
|
|
192
|
-
class ReeDaoLoadAggTest::Book
|
193
|
-
include ReeDto::EntityDSL
|
194
|
-
|
195
|
-
properties(
|
196
|
-
id: Nilor[Integer],
|
197
|
-
user_id: Integer,
|
198
|
-
title: Nilor[String]
|
199
|
-
)
|
200
|
-
|
201
|
-
def set_chapters(chapters)
|
202
|
-
@chapters = chapters; nil
|
203
|
-
end
|
204
|
-
|
205
|
-
def chapters
|
206
|
-
@chapters
|
207
|
-
end
|
208
|
-
|
209
|
-
def set_author(author)
|
210
|
-
@author = author
|
211
|
-
end
|
212
|
-
|
213
|
-
def author
|
214
|
-
@author
|
215
|
-
end
|
216
|
-
|
217
|
-
def set_reviews(reviews)
|
218
|
-
@reviews = reviews; nil
|
219
|
-
end
|
220
|
-
|
221
|
-
def reviews
|
222
|
-
@reviews
|
223
|
-
end
|
224
|
-
|
225
|
-
attr_accessor :title, :user_id
|
226
|
-
end
|
227
|
-
|
228
259
|
class ReeDaoLoadAggTest::Chapter
|
229
260
|
include ReeDto::EntityDSL
|
230
261
|
|
data/lib/ree_lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ree_lib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.56
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ruslan Gatiyatov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-07-
|
11
|
+
date: 2023-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ree
|