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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 77d773db4104deb076fe0ea9d9aa6b8e0fd1218d71731e6d51a70a50be09d569
4
- data.tar.gz: ac943abd83280ff44db19e50991e1ca51aa92cd1f140ccaa9e82cf706fc9dc8e
3
+ metadata.gz: a16fe3f260e9c08dfa590a34ffeafce9413115416aaedc37bcb4ee50fbd5ae67
4
+ data.tar.gz: d93566783538e0ea2eb9aba94938a3eccdb34901197d5e38afa9f03da9e5f826
5
5
  SHA512:
6
- metadata.gz: 6eb4b4567e977e12c59f5246f819dcba9702ccb77fb5e776584f193f6cff18c14d4e7e40d75c0377b0fc905720936f0feb888e2e953b288466f7d777ed7bd633
7
- data.tar.gz: 26ee7d50cf9e346c4cb9614832282d586d0ac767dcd0b65bdb056511ed2e3058f5d1186003e6f30b89a9a661768c7b7153e4d2a3f079185b441f9b7ca5582485
6
+ metadata.gz: d1b98f584c71eb035a29a411161a9556aef71ce4b2d9e292e219e767e335ba9cbfa3c8b7fa49e776d846732f84af7c7f6cc5ce91bcfe5a975bd7cf91a843ad83
7
+ data.tar.gz: b4106abe1f03951c28959f8b9edc4c5f66ff05dcc1788bd2c1e268dd02f0487350ba5074c62eafd73244435dd42a3e034d87e873aaf5c5e11f3791b4884a83f4
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ree_lib (1.0.60)
4
+ ree_lib (1.0.61)
5
5
  binding_of_caller (~> 1.0.0)
6
6
  i18n (~> 1.12.0)
7
7
  loofah (~> 2.18.0)
@@ -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
- process_block(assoc_index, opts[:autoload_children] ||= false, &block) if block_given?
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
- setter: opts[:setter]
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
- name = underscore(demodulize(list.first.class.name))
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 ||= "#{underscore(demodulize(list.first.class.name))}_id".to_sym
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
- value = [] if value.nil? && multiple
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
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ReeLib
4
- VERSION = "1.0.60"
4
+ VERSION = "1.0.61"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ree_lib
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.60
4
+ version: 1.0.61
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ruslan Gatiyatov