dbee 2.0.2 → 3.0.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.
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2019-present, Blue Marble Payroll, LLC
5
+ #
6
+ # This source code is licensed under the MIT license found in the
7
+ # LICENSE file in the root directory of this source tree.
8
+ #
9
+
10
+ require 'spec_helper'
11
+ require_relative '../fixtures/models'
12
+
13
+ describe Dbee::Schema do
14
+ def make_model(model_name)
15
+ raise "no model named '#{model_name}'" unless schema_config.key?(model_name)
16
+
17
+ Dbee::Model.make((schema_config[model_name] || {}).merge('name' => model_name))
18
+ end
19
+
20
+ let(:model_name) do
21
+ 'Theaters, Members, and Movies from DSL'
22
+ end
23
+ let(:schema_config) { yaml_fixture('models.yaml')[model_name] }
24
+
25
+ let(:demographics_model) { make_model('demographic') }
26
+ let(:members_model) { make_model('member') }
27
+ let(:movies_model) { make_model('movie') }
28
+ let(:phone_numbers_model) { make_model('phone_number') }
29
+ let(:theaters_model) { make_model('theater') }
30
+
31
+ let(:subject) { described_class.new(schema_config) }
32
+
33
+ describe '#expand_query_path' do
34
+ specify 'one model case' do
35
+ expect(subject.expand_query_path(members_model, Dbee::KeyPath.new('id'))).to eq []
36
+ end
37
+
38
+ specify 'two model case' do
39
+ expected_path = [[members_model.relationship_for_name('movies'), movies_model]]
40
+ expect(
41
+ subject.expand_query_path(members_model, Dbee::KeyPath.new('movies.id'))
42
+ ).to eq expected_path
43
+ end
44
+
45
+ it 'traverses aliased models' do
46
+ expected_path = [
47
+ [members_model.relationship_for_name('demos'), demographics_model],
48
+ [demographics_model.relationship_for_name('phone_numbers'), phone_numbers_model]
49
+ ]
50
+
51
+ expect(
52
+ subject.expand_query_path(members_model, Dbee::KeyPath.new('demos.phone_numbers.id'))
53
+ ).to eq expected_path
54
+ end
55
+
56
+ it 'raises an error given an unknown relationship' do
57
+ expect do
58
+ subject.expand_query_path(theaters_model, Dbee::KeyPath.new('demographics.id'))
59
+ end.to raise_error("model 'theater' does not have a 'demographics' relationship")
60
+ end
61
+ end
62
+ end
data/spec/dbee_spec.rb CHANGED
@@ -13,59 +13,39 @@ require 'fixtures/models'
13
13
  describe Dbee do
14
14
  describe '#sql' do
15
15
  let(:provider) { Dbee::Providers::NullProvider.new }
16
-
17
- let(:model_hash) do
18
- {
19
- name: 'something'
20
- }
21
- end
22
-
23
- let(:model) { Dbee::Model.make(model_hash) }
24
-
25
16
  let(:query_hash) do
26
17
  {
18
+ from: 'my_model',
27
19
  fields: [
28
20
  { key_path: :a }
29
21
  ]
30
22
  }
31
23
  end
32
-
33
24
  let(:query) { Dbee::Query.make(query_hash) }
25
+ let(:schema) { Dbee::Schema.new({}) }
34
26
 
35
- it 'accepts a hash as a model and passes a Model instance to provider#sql' do
36
- expect(provider).to receive(:sql).with(model, query)
37
-
38
- described_class.sql(model_hash, query, provider)
39
- end
40
-
41
- it 'accepts a Dbee::Model instance as a model and passes a Model instance to provider#sql' do
42
- expect(provider).to receive(:sql).with(model, query)
27
+ it 'accepts a query hash and a Schema and passes them into provider#sql' do
28
+ expect(provider).to receive(:sql).with(schema, query)
43
29
 
44
- described_class.sql(model, query, provider)
30
+ described_class.sql(schema, query_hash, provider)
45
31
  end
46
32
 
47
- it 'accepts a Dbee::Base constant as a model and passes a Model instance to provider#sql' do
48
- model_constant = Models::Theater
49
-
50
- expect(provider).to receive(:sql).with(model_constant.to_model(query.key_chain), query)
51
-
52
- described_class.sql(model_constant, query, provider)
33
+ it 'does not allow a nil schema' do
34
+ expect do
35
+ described_class.sql(nil, query, provider)
36
+ end.to raise_error ArgumentError, /schema or model is required/
53
37
  end
54
38
 
55
- it 'accepts a Dbee::Query instance as a query and passes a Query instance to provider#sql' do
56
- model = Models::Theater.to_model(query.key_chain)
57
-
58
- expect(provider).to receive(:sql).with(model, query)
59
-
60
- described_class.sql(model, query, provider)
39
+ it 'does not allow a nil query' do
40
+ expect do
41
+ described_class.sql(schema, nil, provider)
42
+ end.to raise_error ArgumentError, /query is required/
61
43
  end
62
44
 
63
- it 'accepts a hash as a query and passes a Query instance to provider#sql' do
64
- model = Models::Theater.to_model(query.key_chain)
65
-
66
- expect(provider).to receive(:sql).with(model, query)
67
-
68
- described_class.sql(model, query_hash, provider)
45
+ it 'does not allow a nil provider' do
46
+ expect do
47
+ described_class.sql(schema, query, nil)
48
+ end.to raise_error ArgumentError, /provider is required/
69
49
  end
70
50
  end
71
51
  end
@@ -1,4 +1,4 @@
1
- Theaters, Members, and Movies:
1
+ Theaters, Members, and Movies Tree Based:
2
2
  name: theater
3
3
  table: theaters
4
4
  models:
@@ -119,7 +119,217 @@ Theaters, Members, and Movies:
119
119
  - type: static
120
120
  name: genre
121
121
  value: comedy
122
+
123
+ # Note that since converting from the tree does not have as much context as
124
+ # converting from the DSL, the resulting graph is a bit different.
125
+ Theaters, Members, and Movies from Tree:
126
+ theater:
127
+ table: theaters
128
+ relationships:
129
+ members:
130
+ constraints:
131
+ - type: reference
132
+ parent: id
133
+ name: tid
134
+ - type: reference
135
+ parent: partition
136
+ name: partition
137
+ parent_theater:
138
+ constraints:
139
+ - type: reference
140
+ name: id
141
+ parent: parent_theater_id
142
+ members:
143
+ relationships:
144
+ demos:
145
+ constraints:
146
+ - type: reference
147
+ parent: id
148
+ name: member_id
149
+ movies:
150
+ constraints:
151
+ - type: reference
152
+ parent: id
153
+ name: member_id
154
+ favorite_comic_movies:
155
+ constraints:
156
+ - type: reference
157
+ parent: id
158
+ name: member_id
159
+ - type: static
160
+ name: genre
161
+ value: comic
162
+ favorite_mystery_movies:
163
+ constraints:
164
+ - type: reference
165
+ parent: id
166
+ name: member_id
167
+ - type: static
168
+ name: genre
169
+ value: mystery
170
+ favorite_comedy_movies:
171
+ constraints:
172
+ - type: reference
173
+ parent: id
174
+ name: member_id
175
+ - type: static
176
+ name: genre
177
+ value: comedy
178
+ demos:
179
+ table: demographics
180
+ relationships:
181
+ phone_numbers:
182
+ constraints:
183
+ - type: reference
184
+ parent: id
185
+ name: demographic_id
186
+ phone_numbers:
187
+ movies:
188
+ favorite_comic_movies:
189
+ table: movies
190
+ favorite_mystery_movies:
191
+ table: movies
192
+ favorite_comedy_movies:
193
+ table: movies
194
+ parent_theater:
195
+ table: theaters
196
+ relationships:
197
+ members:
198
+ constraints:
199
+ - type: reference
200
+ parent: id
201
+ name: tid
202
+ - type: reference
203
+ parent: partition
204
+ name: partition
205
+
206
+ Theaters, Members, and Movies from DSL:
207
+ theater:
208
+ table: theaters
209
+ relationships:
210
+ members:
211
+ model: member
212
+ constraints:
213
+ - type: reference
214
+ parent: id
215
+ name: tid
216
+ - type: reference
217
+ parent: partition
218
+ name: partition
219
+ parent_theater:
220
+ model: theater
221
+ constraints:
222
+ - type: reference
223
+ name: id
224
+ parent: parent_theater_id
225
+ member:
226
+ table: members
227
+ relationships:
228
+ movies:
229
+ model: movie
230
+ constraints:
231
+ - type: reference
232
+ parent: id
233
+ name: member_id
234
+ demos:
235
+ model: demographic
236
+ constraints:
237
+ - type: reference
238
+ parent: id
239
+ name: member_id
240
+ favorite_comic_movies:
241
+ model: movie
242
+ constraints:
243
+ - type: reference
244
+ parent: id
245
+ name: member_id
246
+ - type: static
247
+ name: genre
248
+ value: comic
249
+ favorite_mystery_movies:
250
+ model: movie
251
+ constraints:
252
+ - type: reference
253
+ parent: id
254
+ name: member_id
255
+ - type: static
256
+ name: genre
257
+ value: mystery
258
+ favorite_comedy_movies:
259
+ model: movie
260
+ constraints:
261
+ - type: reference
262
+ parent: id
263
+ name: member_id
264
+ - type: static
265
+ name: genre
266
+ value: comedy
267
+ demographic:
268
+ table: demographics
269
+ relationships:
270
+ phone_numbers:
271
+ model: phone_number
272
+ constraints:
273
+ - type: reference
274
+ parent: id
275
+ name: demographic_id
276
+ phone_number:
277
+ table: phone_numbers
278
+ movie:
279
+ table: movies
280
+
122
281
  Readme:
282
+ practice:
283
+ table: practices
284
+ relationships:
285
+ patients:
286
+ model: patient
287
+ constraints:
288
+ - type: reference
289
+ name: practice_id
290
+ parent: id
291
+ patient:
292
+ table: patients
293
+ relationships:
294
+ notes:
295
+ model: note
296
+ constraints:
297
+ - type: reference
298
+ name: patient_id
299
+ parent: id
300
+ work_phone_number:
301
+ model: phone_number
302
+ constraints:
303
+ - type: reference
304
+ name: patient_id
305
+ parent: id
306
+ - type: static
307
+ name: phone_number_type
308
+ value: work
309
+ cell_phone_number:
310
+ model: phone_number
311
+ constraints:
312
+ - type: reference
313
+ name: patient_id
314
+ parent: id
315
+ - type: static
316
+ name: phone_number_type
317
+ value: cell
318
+ fax_phone_number:
319
+ model: phone_number
320
+ constraints:
321
+ - type: reference
322
+ name: patient_id
323
+ parent: id
324
+ - type: static
325
+ name: phone_number_type
326
+ value: fax
327
+ note:
328
+ table: notes
329
+ phone_number:
330
+ table: phones
331
+
332
+ Readme Tree Based:
123
333
  name: practice
124
334
  table: practices
125
335
  models:
@@ -161,63 +371,51 @@ Readme:
161
371
  - type: static
162
372
  name: phone_number_type
163
373
  value: fax
374
+
164
375
  Cycle Example:
165
- name: a
166
- table: as
167
- models:
168
- - name: b1
169
- table: bs
170
- models:
171
- - name: c
172
- table: cs
173
- models:
174
- - name: a
175
- table: as
176
- - name: d
177
- table: ds
178
- models:
179
- - name: a
180
- table: as
181
- - name: b2
182
- table: bs
183
- models:
184
- - name: c
185
- table: cs
186
- models:
187
- - name: a
188
- table: as
189
- - name: d
190
- table: ds
191
- models:
192
- - name: a
193
- table: as
194
- models:
195
- - name: b1
196
- table: bs
197
- models:
198
- - name: c
199
- table: cs
376
+ a:
377
+ table: as
378
+ relationships:
379
+ b1:
380
+ model: b
381
+ b2:
382
+ model: b
383
+ b:
384
+ table: bs
385
+ relationships:
386
+ c:
387
+ d:
388
+ c:
389
+ table: cs
390
+ relationships:
391
+ a:
392
+ d:
393
+ table: ds
394
+ relationships:
395
+ a:
200
396
 
201
397
  Partitioner Example 1:
202
- name: dog
203
- table: animals
204
- partitioners:
205
- - name: type
206
- value: Dog
207
- - name: deleted
208
- value: false
398
+ dog:
399
+ table: animals
400
+ partitioners:
401
+ - name: type
402
+ value: Dog
403
+ - name: deleted
404
+ value: false
209
405
 
210
406
  Partitioner Example 2:
211
- name: owner
212
- table: owners
213
- models:
214
- - name: dogs
215
- table: animals
216
- constraints:
217
- - name: owner_id
218
- parent: id
219
- partitioners:
220
- - name: type
221
- value: Dog
222
- - name: deleted
223
- value: false
407
+ owner:
408
+ table: owners
409
+ relationships:
410
+ dogs:
411
+ model: dog
412
+ constraints:
413
+ - name: owner_id
414
+ parent: id
415
+ dog:
416
+ table: animals
417
+ partitioners:
418
+ - name: type
419
+ value: Dog
420
+ - name: deleted
421
+ value: false