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