ree_lib 1.0.60 → 1.0.61
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 +1 -1
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/association.rb +51 -26
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/associations.rb +5 -4
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/functions/load_agg.rb +11 -3
- data/lib/ree_lib/packages/ree_dao/schemas/ree_dao/functions/load_agg.schema.json +15 -0
- data/lib/ree_lib/packages/ree_dao/spec/ree_dao/functions/load_agg/load_agg_spec.rb +33 -0
- data/lib/ree_lib/packages/ree_dao/spec/ree_dao/functions/load_agg/ree_dao_load_agg_test.rb +17 -0
- data/lib/ree_lib/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a16fe3f260e9c08dfa590a34ffeafce9413115416aaedc37bcb4ee50fbd5ae67
|
4
|
+
data.tar.gz: d93566783538e0ea2eb9aba94938a3eccdb34901197d5e38afa9f03da9e5f826
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d1b98f584c71eb035a29a411161a9556aef71ce4b2d9e292e219e767e335ba9cbfa3c8b7fa49e776d846732f84af7c7f6cc5ce91bcfe5a975bd7cf91a843ad83
|
7
|
+
data.tar.gz: b4106abe1f03951c28959f8b9edc4c5f66ff05dcc1788bd2c1e268dd02f0487350ba5074c62eafd73244435dd42a3e034d87e873aaf5c5e11f3791b4884a83f4
|
data/Gemfile.lock
CHANGED
@@ -2,16 +2,15 @@ module ReeDao
|
|
2
2
|
class Association
|
3
3
|
include Ree::LinkDSL
|
4
4
|
|
5
|
-
link :demodulize, from: :ree_string
|
6
5
|
link :group_by, from: :ree_array
|
7
6
|
link :index_by, from: :ree_array
|
8
|
-
link :underscore, from: :ree_string
|
9
7
|
|
10
|
-
attr_reader :parent, :list, :global_opts
|
8
|
+
attr_reader :parent, :parent_dao_name, :list, :global_opts
|
11
9
|
|
12
|
-
contract(ReeDao::Associations, Array, Ksplat[RestKeys => Any] => Any)
|
13
|
-
def initialize(parent, list, **global_opts)
|
10
|
+
contract(ReeDao::Associations, Symbol, Array, Ksplat[RestKeys => Any] => Any)
|
11
|
+
def initialize(parent, parent_dao_name, list, **global_opts)
|
14
12
|
@parent = parent
|
13
|
+
@parent_dao_name = parent_dao_name
|
15
14
|
@list = list
|
16
15
|
@global_opts = global_opts
|
17
16
|
end
|
@@ -37,13 +36,18 @@ module ReeDao
|
|
37
36
|
Optblock => Nilor[Array]
|
38
37
|
)
|
39
38
|
def load_association(assoc_type, assoc_name, **opts, &block)
|
39
|
+
opts[:autoload_children] ||= false
|
40
|
+
|
40
41
|
assoc_index = load_association_by_type(
|
41
42
|
assoc_type,
|
42
43
|
assoc_name,
|
43
44
|
**opts
|
44
45
|
)
|
45
46
|
|
46
|
-
|
47
|
+
dao = find_dao(assoc_name, parent, opts[:scope])
|
48
|
+
dao_name = dao.first_source_table
|
49
|
+
|
50
|
+
process_block(assoc_index, opts[:autoload_children], opts[:to_dto], dao_name, &block) if block_given?
|
47
51
|
|
48
52
|
list
|
49
53
|
end
|
@@ -57,6 +61,7 @@ module ReeDao
|
|
57
61
|
case type
|
58
62
|
when :belongs_to
|
59
63
|
one_to_one(
|
64
|
+
parent_dao_name,
|
60
65
|
assoc_name,
|
61
66
|
list,
|
62
67
|
scope: opts[:scope],
|
@@ -67,44 +72,46 @@ module ReeDao
|
|
67
72
|
)
|
68
73
|
when :has_one
|
69
74
|
one_to_one(
|
75
|
+
parent_dao_name,
|
70
76
|
assoc_name,
|
71
77
|
list,
|
72
78
|
scope: opts[:scope],
|
73
79
|
primary_key: opts[:primary_key],
|
74
80
|
foreign_key: opts[:foreign_key],
|
81
|
+
to_dto: opts[:to_dto],
|
75
82
|
setter: opts[:setter],
|
76
83
|
reverse: true
|
77
84
|
)
|
78
85
|
when :has_many
|
79
86
|
one_to_many(
|
87
|
+
parent_dao_name,
|
80
88
|
assoc_name,
|
81
89
|
list,
|
82
90
|
scope: opts[:scope],
|
83
91
|
primary_key: opts[:primary_key],
|
84
92
|
foreign_key: opts[:foreign_key],
|
85
|
-
|
86
|
-
)
|
87
|
-
else
|
88
|
-
one_to_many(
|
89
|
-
assoc_name,
|
90
|
-
list,
|
91
|
-
scope: opts[:scope],
|
92
|
-
primary_key: opts[:primary_key],
|
93
|
-
foreign_key: opts[:foreign_key],
|
93
|
+
to_dto: opts[:to_dto],
|
94
94
|
setter: opts[:setter]
|
95
95
|
)
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
99
|
-
contract(Or[Hash, Array], Bool, Block => Any)
|
100
|
-
def process_block(assoc, autoload_children, &block)
|
99
|
+
contract(Or[Hash, Array], Bool, Nilor[Proc], Symbol, Block => Any)
|
100
|
+
def process_block(assoc, autoload_children, to_dto, parent_dao_name, &block)
|
101
101
|
assoc_list = assoc.is_a?(Array) ? assoc : assoc.values.flatten
|
102
102
|
|
103
|
+
if to_dto
|
104
|
+
assoc_list = assoc_list.map do |item|
|
105
|
+
to_dto.call(item)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
103
109
|
if ReeDao::Associations.sync_mode?
|
104
110
|
ReeDao::Associations.new(
|
105
111
|
parent.agg_caller,
|
106
112
|
assoc_list,
|
107
113
|
parent.local_vars,
|
114
|
+
parent_dao_name,
|
108
115
|
autoload_children,
|
109
116
|
**global_opts
|
110
117
|
).instance_exec(assoc_list, &block)
|
@@ -113,6 +120,7 @@ module ReeDao
|
|
113
120
|
parent.agg_caller,
|
114
121
|
assoc_list,
|
115
122
|
parent.local_vars,
|
123
|
+
parent_dao_name,
|
116
124
|
autoload_children,
|
117
125
|
**global_opts
|
118
126
|
).instance_exec(assoc_list, &block)
|
@@ -131,6 +139,7 @@ module ReeDao
|
|
131
139
|
end
|
132
140
|
|
133
141
|
contract(
|
142
|
+
Symbol,
|
134
143
|
Symbol,
|
135
144
|
Array,
|
136
145
|
Kwargs[
|
@@ -138,10 +147,11 @@ module ReeDao
|
|
138
147
|
foreign_key: Nilor[Symbol],
|
139
148
|
scope: Nilor[Sequel::Dataset, Array],
|
140
149
|
setter: Nilor[Or[Symbol, Proc]],
|
150
|
+
to_dto: Nilor[Proc],
|
141
151
|
reverse: Bool
|
142
152
|
] => Or[Hash, Array]
|
143
153
|
)
|
144
|
-
def one_to_one(assoc_name, list, scope: nil, primary_key: :id, foreign_key: nil, setter: nil, reverse: true)
|
154
|
+
def one_to_one(parent_assoc_name, assoc_name, list, scope: nil, primary_key: :id, foreign_key: nil, setter: nil, to_dto: nil, reverse: true)
|
145
155
|
return {} if list.empty?
|
146
156
|
|
147
157
|
primary_key ||= :id
|
@@ -153,8 +163,7 @@ module ReeDao
|
|
153
163
|
|
154
164
|
if reverse
|
155
165
|
if !foreign_key
|
156
|
-
|
157
|
-
foreign_key = "#{name}_id".to_sym
|
166
|
+
foreign_key = "#{parent_assoc_name.to_s.gsub(/e?s$/,'')}_id".to_sym
|
158
167
|
end
|
159
168
|
|
160
169
|
root_ids = list.map(&:id).uniq
|
@@ -172,6 +181,7 @@ module ReeDao
|
|
172
181
|
items = add_scopes(scope, global_opts[assoc_name])
|
173
182
|
end
|
174
183
|
|
184
|
+
|
175
185
|
assoc = index_by(items) { _1.send(reverse ? foreign_key : :id) }
|
176
186
|
|
177
187
|
populate_association(
|
@@ -180,23 +190,26 @@ module ReeDao
|
|
180
190
|
assoc_name,
|
181
191
|
setter: setter,
|
182
192
|
reverse: reverse,
|
183
|
-
primary_key: primary_key
|
193
|
+
primary_key: primary_key,
|
194
|
+
to_dto: to_dto
|
184
195
|
)
|
185
196
|
|
186
197
|
assoc
|
187
198
|
end
|
188
199
|
|
189
200
|
contract(
|
201
|
+
Symbol,
|
190
202
|
Symbol,
|
191
203
|
Array,
|
192
204
|
Kwargs[
|
193
205
|
foreign_key: Nilor[Symbol],
|
194
206
|
primary_key: Nilor[Symbol],
|
195
207
|
scope: Nilor[Sequel::Dataset, Array],
|
196
|
-
setter: Nilor[Or[Symbol, Proc]]
|
208
|
+
setter: Nilor[Or[Symbol, Proc]],
|
209
|
+
to_dto: Nilor[Proc]
|
197
210
|
] => Or[Hash, Array]
|
198
211
|
)
|
199
|
-
def one_to_many(assoc_name, list, primary_key: nil, foreign_key: nil, scope: nil, setter: nil)
|
212
|
+
def one_to_many(parent_assoc_name, assoc_name, list, primary_key: nil, foreign_key: nil, scope: nil, setter: nil, to_dto: nil)
|
200
213
|
return {} if list.empty?
|
201
214
|
|
202
215
|
primary_key ||= :id
|
@@ -207,7 +220,7 @@ module ReeDao
|
|
207
220
|
assoc_dao = nil
|
208
221
|
assoc_dao = find_dao(assoc_name, parent, scope)
|
209
222
|
|
210
|
-
foreign_key ||= "#{
|
223
|
+
foreign_key ||= "#{parent_assoc_name.to_s.gsub(/e?s$/,'')}_id".to_sym
|
211
224
|
|
212
225
|
root_ids = list.map(&:"#{primary_key}")
|
213
226
|
|
@@ -229,6 +242,7 @@ module ReeDao
|
|
229
242
|
assoc_name,
|
230
243
|
setter: setter,
|
231
244
|
primary_key: primary_key,
|
245
|
+
to_dto: to_dto,
|
232
246
|
multiple: true
|
233
247
|
)
|
234
248
|
|
@@ -243,10 +257,11 @@ module ReeDao
|
|
243
257
|
primary_key: Nilor[Symbol],
|
244
258
|
reverse: Nilor[Bool],
|
245
259
|
setter: Nilor[Or[Symbol, Proc]],
|
260
|
+
to_dto: Nilor[Proc],
|
246
261
|
multiple: Bool
|
247
262
|
] => Any
|
248
263
|
)
|
249
|
-
def populate_association(list, association_index, assoc_name, primary_key: nil, reverse: nil, setter: nil, multiple: false)
|
264
|
+
def populate_association(list, association_index, assoc_name, primary_key: nil, reverse: nil, setter: nil, to_dto: nil, multiple: false)
|
250
265
|
assoc_setter = if setter
|
251
266
|
setter
|
252
267
|
else
|
@@ -264,7 +279,17 @@ module ReeDao
|
|
264
279
|
end
|
265
280
|
value = association_index[item.send(key)]
|
266
281
|
|
267
|
-
|
282
|
+
if to_dto && !value.nil?
|
283
|
+
if value.is_a?(Array)
|
284
|
+
value = value.map { to_dto.call(_1) }
|
285
|
+
else
|
286
|
+
value = to_dto.call(value)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
if value.nil? && multiple
|
291
|
+
value = []
|
292
|
+
end
|
268
293
|
|
269
294
|
begin
|
270
295
|
item.send(assoc_setter, value)
|
@@ -2,15 +2,16 @@ module ReeDao
|
|
2
2
|
class Associations
|
3
3
|
include Ree::LinkDSL
|
4
4
|
|
5
|
-
attr_reader :agg_caller, :list, :local_vars, :only, :except, :autoload_children, :global_opts
|
5
|
+
attr_reader :agg_caller, :list, :local_vars, :only, :except, :parent_dao_name, :autoload_children, :global_opts
|
6
6
|
|
7
|
-
def initialize(agg_caller, list, local_vars, autoload_children = false, **opts)
|
7
|
+
def initialize(agg_caller, list, local_vars, parent_dao_name, autoload_children = false, **opts)
|
8
8
|
@agg_caller = agg_caller
|
9
9
|
@list = list
|
10
10
|
@local_vars = local_vars
|
11
11
|
@global_opts = opts || {}
|
12
12
|
@only = opts[:only] if opts[:only]
|
13
13
|
@except = opts[:except] if opts[:except]
|
14
|
+
@parent_dao_name = parent_dao_name
|
14
15
|
@autoload_children = autoload_children
|
15
16
|
|
16
17
|
raise ArgumentError.new("you can't use both :only and :except arguments at the same time") if @only && @except
|
@@ -83,7 +84,7 @@ module ReeDao
|
|
83
84
|
if self.class.sync_mode?
|
84
85
|
return if association_is_not_included?(assoc_name) || list.empty?
|
85
86
|
|
86
|
-
association = Association.new(self, list, **global_opts)
|
87
|
+
association = Association.new(self, parent_dao_name, list, **global_opts)
|
87
88
|
if assoc_type == :field
|
88
89
|
association.handle_field(assoc_name, opts)
|
89
90
|
else
|
@@ -94,7 +95,7 @@ module ReeDao
|
|
94
95
|
return { association_threads: @assoc_threads, field_threads: @field_threads }
|
95
96
|
end
|
96
97
|
|
97
|
-
association = Association.new(self, list, **global_opts)
|
98
|
+
association = Association.new(self, parent_dao_name, list, **global_opts)
|
98
99
|
|
99
100
|
if assoc_type == :field
|
100
101
|
field_proc = opts
|
@@ -4,6 +4,8 @@ class ReeDao::LoadAgg
|
|
4
4
|
include Ree::FnDSL
|
5
5
|
|
6
6
|
fn :load_agg do
|
7
|
+
link :demodulize, from: :ree_string
|
8
|
+
link :underscore, from: :ree_string
|
7
9
|
link "ree_dao/associations", -> { Associations }
|
8
10
|
link "ree_dao/contract/dao_dataset_contract", -> { DaoDatasetContract }
|
9
11
|
link "ree_dao/contract/entity_contract", -> { EntityContract }
|
@@ -34,6 +36,12 @@ class ReeDao::LoadAgg
|
|
34
36
|
ids_or_scope
|
35
37
|
end
|
36
38
|
|
39
|
+
if dao
|
40
|
+
dao_name = dao.first_source_table
|
41
|
+
else
|
42
|
+
dao_name = underscore(demodulize(scope.first.class.name)).to_sym
|
43
|
+
end
|
44
|
+
|
37
45
|
list = scope.is_a?(Sequel::Dataset) ? scope.all : scope
|
38
46
|
|
39
47
|
if opts[:to_dto]
|
@@ -42,7 +50,7 @@ class ReeDao::LoadAgg
|
|
42
50
|
end
|
43
51
|
end
|
44
52
|
|
45
|
-
load_associations(list, **opts, &block) if block_given?
|
53
|
+
load_associations(dao_name, list, **opts, &block) if block_given?
|
46
54
|
|
47
55
|
if ids_or_scope.is_a?(Array)
|
48
56
|
list.sort_by { ids_or_scope.index(_1.id) }
|
@@ -53,7 +61,7 @@ class ReeDao::LoadAgg
|
|
53
61
|
|
54
62
|
private
|
55
63
|
|
56
|
-
def load_associations(list, **opts, &block)
|
64
|
+
def load_associations(dao_name, list, **opts, &block)
|
57
65
|
return if list.empty?
|
58
66
|
|
59
67
|
local_vars = block.binding.eval(<<-CODE, __FILE__, __LINE__ + 1)
|
@@ -63,7 +71,7 @@ class ReeDao::LoadAgg
|
|
63
71
|
|
64
72
|
agg_caller = block.binding.eval("self")
|
65
73
|
|
66
|
-
associations = Associations.new(agg_caller, list, local_vars, **opts).instance_exec(list, &block)
|
74
|
+
associations = Associations.new(agg_caller, list, local_vars, dao_name, **opts).instance_exec(list, &block)
|
67
75
|
|
68
76
|
if ReeDao.load_sync_associations_enabled?
|
69
77
|
associations
|
@@ -38,6 +38,21 @@
|
|
38
38
|
}
|
39
39
|
],
|
40
40
|
"links": [
|
41
|
+
{
|
42
|
+
"target": "demodulize",
|
43
|
+
"package_name": "ree_string",
|
44
|
+
"as": "demodulize",
|
45
|
+
"imports": [
|
46
|
+
|
47
|
+
]
|
48
|
+
},
|
49
|
+
{
|
50
|
+
"target": "underscore",
|
51
|
+
"package_name": "ree_string",
|
52
|
+
"as": "underscore",
|
53
|
+
"imports": [
|
41
54
|
|
55
|
+
]
|
56
|
+
}
|
42
57
|
]
|
43
58
|
}
|
@@ -153,6 +153,9 @@ RSpec.describe :load_agg do
|
|
153
153
|
|
154
154
|
aggregate :users_agg_with_dto do
|
155
155
|
link :users, from: :ree_dao_load_agg_test
|
156
|
+
link :books, from: :ree_dao_load_agg_test
|
157
|
+
link :authors, from: :ree_dao_load_agg_test
|
158
|
+
link :chapters, from: :ree_dao_load_agg_test
|
156
159
|
link :organizations, from: :ree_dao_load_agg_test
|
157
160
|
link :load_agg, from: :ree_dao
|
158
161
|
end
|
@@ -160,8 +163,27 @@ RSpec.describe :load_agg do
|
|
160
163
|
def call(ids_or_scope, **opts)
|
161
164
|
load_agg(users, ids_or_scope, **opts) do
|
162
165
|
belongs_to :organization
|
166
|
+
|
167
|
+
has_many :books, -> { books_opts } do
|
168
|
+
has_one :author, -> { author_opts }
|
169
|
+
has_many :chapters, -> { chapters_opts }
|
170
|
+
end
|
163
171
|
end
|
164
172
|
end
|
173
|
+
|
174
|
+
private
|
175
|
+
|
176
|
+
def books_opts
|
177
|
+
{ to_dto: -> (book) { ReeDaoLoadAggTest::BookDto.new(book) }}
|
178
|
+
end
|
179
|
+
|
180
|
+
def author_opts
|
181
|
+
{ to_dto: -> (author) { ReeDaoLoadAggTest::AuthorDto.new(author) }}
|
182
|
+
end
|
183
|
+
|
184
|
+
def chapters_opts
|
185
|
+
{ to_dto: -> (chapter) { ReeDaoLoadAggTest::ChapterDto.new(chapter) }}
|
186
|
+
end
|
165
187
|
end
|
166
188
|
|
167
189
|
class ReeDaoLoadAggTest::UsersAggAutoloadBooksChildren
|
@@ -370,6 +392,12 @@ RSpec.describe :load_agg do
|
|
370
392
|
users.put(user_1)
|
371
393
|
users.put(user_2)
|
372
394
|
|
395
|
+
book_1 = ReeDaoLoadAggTest::Book.new(user_id: user_1.id, title: "1984")
|
396
|
+
books.put(book_1)
|
397
|
+
|
398
|
+
authors.put(ReeDaoLoadAggTest::Author.new(book_id: book_1.id, name: "George Orwell"))
|
399
|
+
chapters.put(ReeDaoLoadAggTest::Chapter.new(book_id: book_1.id, title: "interlude"))
|
400
|
+
|
373
401
|
res = users_agg_with_dto.call(
|
374
402
|
users.all,
|
375
403
|
to_dto: -> (user) {
|
@@ -382,7 +410,12 @@ RSpec.describe :load_agg do
|
|
382
410
|
}
|
383
411
|
)
|
384
412
|
|
413
|
+
book = res.first.books.first
|
414
|
+
|
385
415
|
expect(res.first.class).to eq(ReeDaoLoadAggTest::UserDto)
|
416
|
+
expect(book.class).to eq(ReeDaoLoadAggTest::BookDto)
|
417
|
+
expect(book.author.class).to eq(ReeDaoLoadAggTest::AuthorDto)
|
418
|
+
expect(book.chapters.first.class).to eq(ReeDaoLoadAggTest::ChapterDto)
|
386
419
|
}
|
387
420
|
|
388
421
|
it {
|
@@ -75,6 +75,9 @@ class ReeDaoLoadAggTest::Book
|
|
75
75
|
attr_accessor :title, :user_id
|
76
76
|
end
|
77
77
|
|
78
|
+
class ReeDaoLoadAggTest::BookDto < SimpleDelegator
|
79
|
+
end
|
80
|
+
|
78
81
|
class ReeDaoLoadAggTest::User
|
79
82
|
include ReeDto::EntityDSL
|
80
83
|
|
@@ -159,6 +162,14 @@ class ReeDaoLoadAggTest::UserDto
|
|
159
162
|
def organization
|
160
163
|
@organization
|
161
164
|
end
|
165
|
+
|
166
|
+
def set_books(books)
|
167
|
+
@books = books; nil
|
168
|
+
end
|
169
|
+
|
170
|
+
def books
|
171
|
+
@books
|
172
|
+
end
|
162
173
|
end
|
163
174
|
|
164
175
|
class ReeDaoLoadAggTest::Organization
|
@@ -276,6 +287,9 @@ class ReeDaoLoadAggTest::Chapter
|
|
276
287
|
attr_accessor :title, :book_id
|
277
288
|
end
|
278
289
|
|
290
|
+
class ReeDaoLoadAggTest::ChapterDto < SimpleDelegator
|
291
|
+
end
|
292
|
+
|
279
293
|
class ReeDaoLoadAggTest::Author
|
280
294
|
include ReeDto::EntityDSL
|
281
295
|
|
@@ -288,6 +302,9 @@ class ReeDaoLoadAggTest::Author
|
|
288
302
|
attr_accessor :name, :book_id
|
289
303
|
end
|
290
304
|
|
305
|
+
class ReeDaoLoadAggTest::AuthorDto < SimpleDelegator
|
306
|
+
end
|
307
|
+
|
291
308
|
class ReeDaoLoadAggTest::Review
|
292
309
|
include ReeDto::EntityDSL
|
293
310
|
|
data/lib/ree_lib/version.rb
CHANGED