dbee 1.0.0.pre.alpha
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 +7 -0
- data/.editorconfig +8 -0
- data/.gitignore +6 -0
- data/.rubocop.yml +23 -0
- data/.ruby-version +1 -0
- data/.travis.yml +26 -0
- data/CHANGELOG.md +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +5 -0
- data/Guardfile +16 -0
- data/LICENSE +7 -0
- data/README.md +368 -0
- data/Rakefile +15 -0
- data/bin/console +18 -0
- data/dbee.gemspec +33 -0
- data/lib/dbee/base.rb +109 -0
- data/lib/dbee/model/constraints/base.rb +36 -0
- data/lib/dbee/model/constraints/reference.rb +42 -0
- data/lib/dbee/model/constraints/static.rb +40 -0
- data/lib/dbee/model/constraints.rb +26 -0
- data/lib/dbee/model.rb +79 -0
- data/lib/dbee/providers/null_provider.rb +21 -0
- data/lib/dbee/providers.rb +10 -0
- data/lib/dbee/query/field.rb +41 -0
- data/lib/dbee/query/filters/base.rb +39 -0
- data/lib/dbee/query/filters/contains.rb +19 -0
- data/lib/dbee/query/filters/equals.rb +19 -0
- data/lib/dbee/query/filters/greater_than.rb +19 -0
- data/lib/dbee/query/filters/greater_than_or_equal_to.rb +19 -0
- data/lib/dbee/query/filters/less_than.rb +19 -0
- data/lib/dbee/query/filters/less_than_or_equal_to.rb +19 -0
- data/lib/dbee/query/filters/not_contain.rb +19 -0
- data/lib/dbee/query/filters/not_equals.rb +19 -0
- data/lib/dbee/query/filters/not_start_with.rb +19 -0
- data/lib/dbee/query/filters/starts_with.rb +19 -0
- data/lib/dbee/query/filters.rb +40 -0
- data/lib/dbee/query/key_path.rb +54 -0
- data/lib/dbee/query/sorter.rb +53 -0
- data/lib/dbee/query.rb +45 -0
- data/lib/dbee/version.rb +12 -0
- data/lib/dbee.rb +28 -0
- data/spec/dbee/base_spec.rb +35 -0
- data/spec/dbee/model/constraints/base_spec.rb +42 -0
- data/spec/dbee/model/constraints/reference_spec.rb +37 -0
- data/spec/dbee/model/constraints/static_spec.rb +29 -0
- data/spec/dbee/model/constraints_spec.rb +25 -0
- data/spec/dbee/model_spec.rb +113 -0
- data/spec/dbee/providers/null_provider_spec.rb +22 -0
- data/spec/dbee/query/field_spec.rb +42 -0
- data/spec/dbee/query/filters/base_spec.rb +42 -0
- data/spec/dbee/query/filters_spec.rb +33 -0
- data/spec/dbee/query/key_path_spec.rb +35 -0
- data/spec/dbee/query/sorter_spec.rb +72 -0
- data/spec/dbee/query_spec.rb +94 -0
- data/spec/dbee_spec.rb +60 -0
- data/spec/fixtures/models.rb +115 -0
- data/spec/fixtures/models.yaml +101 -0
- data/spec/spec_helper.rb +52 -0
- metadata +239 -0
@@ -0,0 +1,72 @@
|
|
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
|
+
|
12
|
+
describe Dbee::Query::Sorter do
|
13
|
+
it 'should act as hashable' do
|
14
|
+
expect(described_class).to respond_to(:make)
|
15
|
+
expect(described_class).to respond_to(:array)
|
16
|
+
end
|
17
|
+
|
18
|
+
context '#initialize' do
|
19
|
+
specify 'key_path is required' do
|
20
|
+
expect { described_class.new(key_path: '') }.to raise_error(ArgumentError)
|
21
|
+
expect { described_class.new(key_path: nil) }.to raise_error(ArgumentError)
|
22
|
+
expect { described_class.new }.to raise_error(ArgumentError)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'equality' do
|
27
|
+
let(:config) { { key_path: 'a.b.c', direction: :descending } }
|
28
|
+
|
29
|
+
subject { described_class.new(config) }
|
30
|
+
|
31
|
+
specify '#hash produces same output as concatenated string hash of key_path and direction' do
|
32
|
+
expect(subject.hash).to eq("#{config[:key_path]}#{config[:direction]}".hash)
|
33
|
+
end
|
34
|
+
|
35
|
+
specify '#== and #eql? compare attributes' do
|
36
|
+
object2 = described_class.new(config)
|
37
|
+
|
38
|
+
expect(subject).to eq(object2)
|
39
|
+
expect(subject).to eql(object2)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'direction helpers' do
|
44
|
+
context 'when direction is ascending' do
|
45
|
+
let(:config) { { key_path: 'a.b.c' } }
|
46
|
+
|
47
|
+
subject { described_class.new(config) }
|
48
|
+
|
49
|
+
it '#ascending? is true' do
|
50
|
+
expect(subject.ascending?).to be true
|
51
|
+
end
|
52
|
+
|
53
|
+
it '#descending? is false' do
|
54
|
+
expect(subject.descending?).to be false
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'when direction is descending' do
|
59
|
+
let(:config) { { key_path: 'a.b.c', direction: :descending } }
|
60
|
+
|
61
|
+
subject { described_class.new(config) }
|
62
|
+
|
63
|
+
it '#ascending? is false' do
|
64
|
+
expect(subject.ascending?).to be false
|
65
|
+
end
|
66
|
+
|
67
|
+
it '#descending? is true' do
|
68
|
+
expect(subject.descending?).to be true
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,94 @@
|
|
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
|
+
|
12
|
+
describe Dbee::Query do
|
13
|
+
let(:config) do
|
14
|
+
{
|
15
|
+
fields: [
|
16
|
+
{ key_path: 'matt.nick.sam', display: 'some display' },
|
17
|
+
{ key_path: 'katie' },
|
18
|
+
{ key_path: 'jordan.pippen' }
|
19
|
+
],
|
20
|
+
sorters: [
|
21
|
+
{ key_path: :sort_me },
|
22
|
+
{ key_path: :sort_me_too, direction: :descending }
|
23
|
+
],
|
24
|
+
limit: 125
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
subject { described_class.make(config) }
|
29
|
+
|
30
|
+
specify '#eql? compares attributes' do
|
31
|
+
expect(subject).to eq(described_class.make(config))
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'README examples' do
|
35
|
+
EXAMPLES = {
|
36
|
+
'Get all practices' => {
|
37
|
+
fields: [
|
38
|
+
{ key_path: 'id' },
|
39
|
+
{ key_path: 'active' },
|
40
|
+
{ key_path: 'name' }
|
41
|
+
]
|
42
|
+
},
|
43
|
+
'Get all practices, limit to 10, and sort by name (descending) then id (ascending)' => {
|
44
|
+
fields: [
|
45
|
+
{ key_path: 'id' },
|
46
|
+
{ key_path: 'active' },
|
47
|
+
{ key_path: 'name' }
|
48
|
+
],
|
49
|
+
sorters: [
|
50
|
+
{ key_path: 'name', direction: :descending },
|
51
|
+
{ key_path: 'id' }
|
52
|
+
],
|
53
|
+
limit: 10
|
54
|
+
},
|
55
|
+
"Get top 5 active practices and patient whose name start with 'Sm':" => {
|
56
|
+
fields: [
|
57
|
+
{ key_path: 'name', display: 'Practice Name' },
|
58
|
+
{ key_path: 'patients.first', display: 'Patient First Name' },
|
59
|
+
{ key_path: 'patients.middle', display: 'Patient Middle Name' },
|
60
|
+
{ key_path: 'patients.last', display: 'Patient Last Name' }
|
61
|
+
],
|
62
|
+
filters: [
|
63
|
+
{ type: :equals, key_path: 'active', value: true },
|
64
|
+
{ type: :starts_with, key_path: 'patients.last', value: 'Sm' }
|
65
|
+
],
|
66
|
+
limit: 5
|
67
|
+
},
|
68
|
+
'Get practice IDs, patient IDs, names, and cell phone numbers that starts with 555' => {
|
69
|
+
fields: [
|
70
|
+
{ key_path: 'id', display: 'Practice ID #' },
|
71
|
+
{ key_path: 'patients.id', display: 'Patient ID #' },
|
72
|
+
{ key_path: 'patients.first', display: 'Patient First Name' },
|
73
|
+
{ key_path: 'patients.middle', display: 'Patient Middle Name' },
|
74
|
+
{ key_path: 'patients.last', display: 'Patient Last Name' },
|
75
|
+
{ key_path: 'patients.cell_phone_numbers.phone_number', display: 'Patient Cell #' }
|
76
|
+
],
|
77
|
+
filters: [
|
78
|
+
{ type: :equals, key_path: 'active', value: true },
|
79
|
+
{
|
80
|
+
type: :starts_with,
|
81
|
+
key_path: 'patients.cell_phone_numbers.phone_number',
|
82
|
+
value: '555'
|
83
|
+
}
|
84
|
+
]
|
85
|
+
}
|
86
|
+
}.freeze
|
87
|
+
|
88
|
+
EXAMPLES.each_pair do |name, query|
|
89
|
+
specify name do
|
90
|
+
expect(described_class.make(query)).to be_a(described_class)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/spec/dbee_spec.rb
ADDED
@@ -0,0 +1,60 @@
|
|
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 'fixtures/models'
|
12
|
+
|
13
|
+
describe Dbee do
|
14
|
+
describe '#sql' do
|
15
|
+
let(:provider) { Dbee::Providers::NullProvider.new }
|
16
|
+
|
17
|
+
let(:query) { {} }
|
18
|
+
|
19
|
+
it 'accepts a hash as a model and passes a Model instance to provider#sql' do
|
20
|
+
model = { name: 'something' }
|
21
|
+
|
22
|
+
expect(provider).to receive(:sql).with(Dbee::Model.make(model), Dbee::Query.make(query))
|
23
|
+
|
24
|
+
described_class.sql(model, query, provider)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'accepts a Dbee::Model instance as a model and passes a Model instance to provider#sql' do
|
28
|
+
model = Dbee::Model.make(name: 'something')
|
29
|
+
|
30
|
+
expect(provider).to receive(:sql).with(Dbee::Model.make(model), Dbee::Query.make(query))
|
31
|
+
|
32
|
+
described_class.sql(model, query, provider)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'accepts a Dbee::Base constant as a model and passes a Model instance to provider#sql' do
|
36
|
+
model = Models::Theaters
|
37
|
+
|
38
|
+
expect(provider).to receive(:sql).with(model.to_model, Dbee::Query.make(query))
|
39
|
+
|
40
|
+
described_class.sql(model, query, provider)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'accepts a Dbee::Query instance as a query and passes a Query instance to provider#sql' do
|
44
|
+
model = Models::Theaters
|
45
|
+
query = Dbee::Query.make(query)
|
46
|
+
|
47
|
+
expect(provider).to receive(:sql).with(model.to_model, Dbee::Query.make(query))
|
48
|
+
|
49
|
+
described_class.sql(model, query, provider)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'accepts a hash as a query and passes a Query instance to provider#sql' do
|
53
|
+
model = Models::Theaters
|
54
|
+
|
55
|
+
expect(provider).to receive(:sql).with(model.to_model, Dbee::Query.make(query))
|
56
|
+
|
57
|
+
described_class.sql(model, query, provider)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,115 @@
|
|
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
|
+
module Models
|
11
|
+
class Movies < Dbee::Base
|
12
|
+
end
|
13
|
+
|
14
|
+
class PhoneNumbers < Dbee::Base
|
15
|
+
end
|
16
|
+
|
17
|
+
class Demographics < Dbee::Base
|
18
|
+
association :phone_numbers, model: PhoneNumbers,
|
19
|
+
constraints: {
|
20
|
+
type: :reference,
|
21
|
+
name: :demographic_id,
|
22
|
+
parent: :id
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
class MembersBase < Dbee::Base
|
27
|
+
association :demos, model: Demographics,
|
28
|
+
constraints: { type: :reference, name: :member_id, parent: :id }
|
29
|
+
|
30
|
+
association :movies, model: Movies,
|
31
|
+
constraints: { type: :reference, name: :member_id, parent: :id }
|
32
|
+
end
|
33
|
+
|
34
|
+
class Members < MembersBase
|
35
|
+
association :favorite_comic_movies, model: Movies, constraints: [
|
36
|
+
{ type: :reference, name: :member_id, parent: :id },
|
37
|
+
{ type: :static, name: :genre, value: 'comic' }
|
38
|
+
]
|
39
|
+
|
40
|
+
association :favorite_mystery_movies, model: Movies, constraints: [
|
41
|
+
{ type: :reference, name: :member_id, parent: :id },
|
42
|
+
{ type: :static, name: :genre, value: 'mystery' }
|
43
|
+
]
|
44
|
+
|
45
|
+
association :favorite_comedy_movies, model: Movies, constraints: [
|
46
|
+
{ type: :reference, name: :member_id, parent: :id },
|
47
|
+
{ type: :static, name: :genre, value: 'comedy' }
|
48
|
+
]
|
49
|
+
end
|
50
|
+
|
51
|
+
class TheatersBase < Dbee::Base
|
52
|
+
end
|
53
|
+
|
54
|
+
class Theaters < TheatersBase
|
55
|
+
association :members, model: Members, constraints: [
|
56
|
+
{ type: :reference, name: :tid, parent: :id },
|
57
|
+
{ type: :reference, name: :partition, parent: :partition }
|
58
|
+
]
|
59
|
+
end
|
60
|
+
|
61
|
+
class A < Dbee::Base
|
62
|
+
table 'table_set_to_a'
|
63
|
+
end
|
64
|
+
|
65
|
+
class B < A
|
66
|
+
table 'table_set_to_b'
|
67
|
+
end
|
68
|
+
|
69
|
+
class C < A
|
70
|
+
end
|
71
|
+
|
72
|
+
class D < A
|
73
|
+
table ''
|
74
|
+
end
|
75
|
+
|
76
|
+
class E < B
|
77
|
+
table 'table_set_to_e'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
module ReadmeDataModels
|
82
|
+
class PhoneNumbers < Dbee::Base
|
83
|
+
table :phones
|
84
|
+
end
|
85
|
+
|
86
|
+
class Notes < Dbee::Base
|
87
|
+
end
|
88
|
+
|
89
|
+
class Patients < Dbee::Base
|
90
|
+
association :notes, model: Notes, constraints: {
|
91
|
+
type: :reference, name: :patient_id, parent: :id
|
92
|
+
}
|
93
|
+
|
94
|
+
association :work_phone_number, model: PhoneNumbers, constraints: [
|
95
|
+
{ type: :reference, name: :patient_id, parent: :id },
|
96
|
+
{ type: :static, name: :phone_number_type, value: 'work' }
|
97
|
+
]
|
98
|
+
|
99
|
+
association :cell_phone_number, model: PhoneNumbers, constraints: [
|
100
|
+
{ type: :reference, name: :patient_id, parent: :id },
|
101
|
+
{ type: :static, name: :phone_number_type, value: 'cell' }
|
102
|
+
]
|
103
|
+
|
104
|
+
association :fax_phone_number, model: PhoneNumbers, constraints: [
|
105
|
+
{ type: :reference, name: :patient_id, parent: :id },
|
106
|
+
{ type: :static, name: :phone_number_type, value: 'fax' }
|
107
|
+
]
|
108
|
+
end
|
109
|
+
|
110
|
+
class Practices < Dbee::Base
|
111
|
+
association :patients, model: Patients, constraints: {
|
112
|
+
type: :reference, name: :practice_id, parent: :id
|
113
|
+
}
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
Theaters, Members, and Movies:
|
2
|
+
name: theaters
|
3
|
+
table: theaters
|
4
|
+
models:
|
5
|
+
- name: members
|
6
|
+
table: members
|
7
|
+
constraints:
|
8
|
+
- type: reference
|
9
|
+
parent: id
|
10
|
+
name: tid
|
11
|
+
- type: reference
|
12
|
+
parent: partition
|
13
|
+
name: partition
|
14
|
+
models:
|
15
|
+
- name: demos
|
16
|
+
table: demographics
|
17
|
+
constraints:
|
18
|
+
- type: reference
|
19
|
+
parent: id
|
20
|
+
name: member_id
|
21
|
+
models:
|
22
|
+
- name: phone_numbers
|
23
|
+
table: phone_numbers
|
24
|
+
constraints:
|
25
|
+
- type: reference
|
26
|
+
parent: id
|
27
|
+
name: demographic_id
|
28
|
+
- name: movies
|
29
|
+
table: movies
|
30
|
+
constraints:
|
31
|
+
- type: reference
|
32
|
+
parent: id
|
33
|
+
name: member_id
|
34
|
+
- name: favorite_comic_movies
|
35
|
+
table: movies
|
36
|
+
constraints:
|
37
|
+
- type: reference
|
38
|
+
parent: id
|
39
|
+
name: member_id
|
40
|
+
- type: static
|
41
|
+
name: genre
|
42
|
+
value: comic
|
43
|
+
- name: favorite_mystery_movies
|
44
|
+
table: movies
|
45
|
+
constraints:
|
46
|
+
- type: reference
|
47
|
+
parent: id
|
48
|
+
name: member_id
|
49
|
+
- type: static
|
50
|
+
name: genre
|
51
|
+
value: mystery
|
52
|
+
- name: favorite_comedy_movies
|
53
|
+
table: movies
|
54
|
+
constraints:
|
55
|
+
- type: reference
|
56
|
+
parent: id
|
57
|
+
name: member_id
|
58
|
+
- type: static
|
59
|
+
name: genre
|
60
|
+
value: comedy
|
61
|
+
Readme:
|
62
|
+
name: practices
|
63
|
+
models:
|
64
|
+
- name: patients
|
65
|
+
constraints:
|
66
|
+
- type: reference
|
67
|
+
name: practice_id
|
68
|
+
parent: id
|
69
|
+
models:
|
70
|
+
- name: notes
|
71
|
+
constraints:
|
72
|
+
- type: reference
|
73
|
+
name: patient_id
|
74
|
+
parent: id
|
75
|
+
- name: work_phone_number
|
76
|
+
table: phones
|
77
|
+
constraints:
|
78
|
+
- type: reference
|
79
|
+
name: patient_id
|
80
|
+
parent: id
|
81
|
+
- type: static
|
82
|
+
name: phone_number_type
|
83
|
+
value: work
|
84
|
+
- name: cell_phone_number
|
85
|
+
table: phones
|
86
|
+
constraints:
|
87
|
+
- type: reference
|
88
|
+
name: patient_id
|
89
|
+
parent: id
|
90
|
+
- type: static
|
91
|
+
name: phone_number_type
|
92
|
+
value: cell
|
93
|
+
- name: fax_phone_number
|
94
|
+
table: phones
|
95
|
+
constraints:
|
96
|
+
- type: reference
|
97
|
+
name: patient_id
|
98
|
+
parent: id
|
99
|
+
- type: static
|
100
|
+
name: phone_number_type
|
101
|
+
value: fax
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2018-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 'yaml'
|
11
|
+
require 'pry'
|
12
|
+
|
13
|
+
unless ENV['DISABLE_SIMPLECOV'] == 'true'
|
14
|
+
require 'simplecov'
|
15
|
+
require 'simplecov-console'
|
16
|
+
|
17
|
+
SimpleCov.formatter = SimpleCov::Formatter::Console
|
18
|
+
SimpleCov.start do
|
19
|
+
add_filter %r{\A/spec/}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
require './lib/dbee'
|
24
|
+
|
25
|
+
def fixture_path(*filename)
|
26
|
+
File.join('spec', 'fixtures', filename)
|
27
|
+
end
|
28
|
+
|
29
|
+
def yaml_fixture(*filename)
|
30
|
+
YAML.safe_load(fixture(*filename))
|
31
|
+
end
|
32
|
+
|
33
|
+
def fixture(*filename)
|
34
|
+
File.open(fixture_path(*filename), 'r:bom|utf-8').read
|
35
|
+
end
|
36
|
+
|
37
|
+
def yaml_fixture_files(*directory)
|
38
|
+
Dir[File.join('spec', 'fixtures', *directory, '*.yaml')].map do |filename|
|
39
|
+
[
|
40
|
+
filename,
|
41
|
+
yaml_file_read(filename)
|
42
|
+
]
|
43
|
+
end.to_h
|
44
|
+
end
|
45
|
+
|
46
|
+
def yaml_file_read(*filename)
|
47
|
+
YAML.safe_load(file_read(*filename))
|
48
|
+
end
|
49
|
+
|
50
|
+
def file_read(*filename)
|
51
|
+
File.open(File.join(*filename), 'r:bom|utf-8').read
|
52
|
+
end
|