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.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +8 -0
  3. data/.gitignore +6 -0
  4. data/.rubocop.yml +23 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +26 -0
  7. data/CHANGELOG.md +7 -0
  8. data/CODE_OF_CONDUCT.md +74 -0
  9. data/Gemfile +5 -0
  10. data/Guardfile +16 -0
  11. data/LICENSE +7 -0
  12. data/README.md +368 -0
  13. data/Rakefile +15 -0
  14. data/bin/console +18 -0
  15. data/dbee.gemspec +33 -0
  16. data/lib/dbee/base.rb +109 -0
  17. data/lib/dbee/model/constraints/base.rb +36 -0
  18. data/lib/dbee/model/constraints/reference.rb +42 -0
  19. data/lib/dbee/model/constraints/static.rb +40 -0
  20. data/lib/dbee/model/constraints.rb +26 -0
  21. data/lib/dbee/model.rb +79 -0
  22. data/lib/dbee/providers/null_provider.rb +21 -0
  23. data/lib/dbee/providers.rb +10 -0
  24. data/lib/dbee/query/field.rb +41 -0
  25. data/lib/dbee/query/filters/base.rb +39 -0
  26. data/lib/dbee/query/filters/contains.rb +19 -0
  27. data/lib/dbee/query/filters/equals.rb +19 -0
  28. data/lib/dbee/query/filters/greater_than.rb +19 -0
  29. data/lib/dbee/query/filters/greater_than_or_equal_to.rb +19 -0
  30. data/lib/dbee/query/filters/less_than.rb +19 -0
  31. data/lib/dbee/query/filters/less_than_or_equal_to.rb +19 -0
  32. data/lib/dbee/query/filters/not_contain.rb +19 -0
  33. data/lib/dbee/query/filters/not_equals.rb +19 -0
  34. data/lib/dbee/query/filters/not_start_with.rb +19 -0
  35. data/lib/dbee/query/filters/starts_with.rb +19 -0
  36. data/lib/dbee/query/filters.rb +40 -0
  37. data/lib/dbee/query/key_path.rb +54 -0
  38. data/lib/dbee/query/sorter.rb +53 -0
  39. data/lib/dbee/query.rb +45 -0
  40. data/lib/dbee/version.rb +12 -0
  41. data/lib/dbee.rb +28 -0
  42. data/spec/dbee/base_spec.rb +35 -0
  43. data/spec/dbee/model/constraints/base_spec.rb +42 -0
  44. data/spec/dbee/model/constraints/reference_spec.rb +37 -0
  45. data/spec/dbee/model/constraints/static_spec.rb +29 -0
  46. data/spec/dbee/model/constraints_spec.rb +25 -0
  47. data/spec/dbee/model_spec.rb +113 -0
  48. data/spec/dbee/providers/null_provider_spec.rb +22 -0
  49. data/spec/dbee/query/field_spec.rb +42 -0
  50. data/spec/dbee/query/filters/base_spec.rb +42 -0
  51. data/spec/dbee/query/filters_spec.rb +33 -0
  52. data/spec/dbee/query/key_path_spec.rb +35 -0
  53. data/spec/dbee/query/sorter_spec.rb +72 -0
  54. data/spec/dbee/query_spec.rb +94 -0
  55. data/spec/dbee_spec.rb +60 -0
  56. data/spec/fixtures/models.rb +115 -0
  57. data/spec/fixtures/models.yaml +101 -0
  58. data/spec/spec_helper.rb +52 -0
  59. 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
@@ -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