ree_lib 1.0.60 → 1.0.61

Sign up to get free protection for your applications and to get access to all the features.
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