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,54 @@
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 Dbee
11
+ class Query
12
+ # This class represents a relative path from a model to a column. For example:
13
+ # Say we have a model called "users" which is represented by a "users" table.
14
+ # The "users" table also has a one-to-many relationship with a "phone_numbers" table, which
15
+ # is modeled as a nested model under "users" as "phone_numbers". Then, to get the column:
16
+ # "area_code", you would use: "phone_numbers.area_code".
17
+ # Say the column "name" is located on "users", you could use the key path: "name".
18
+ # This also works for deeper nested columns in the same fashion.
19
+ class KeyPath
20
+ extend Forwardable
21
+
22
+ class << self
23
+ def get(obj)
24
+ obj.is_a?(self.class) ? obj : new(obj)
25
+ end
26
+ end
27
+
28
+ SPLIT_CHAR = '.'
29
+
30
+ attr_reader :value, :ancestor_names, :column_name
31
+
32
+ def_delegators :value, :to_s
33
+
34
+ def initialize(value)
35
+ raise 'Value is required' if value.to_s.empty?
36
+
37
+ @value = value.to_s
38
+ @ancestor_names = value.to_s.split(SPLIT_CHAR)
39
+ @column_name = @ancestor_names.pop
40
+
41
+ freeze
42
+ end
43
+
44
+ def hash
45
+ value.hash
46
+ end
47
+
48
+ def ==(other)
49
+ other.to_s == to_s
50
+ end
51
+ alias eql? ==
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,53 @@
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_relative 'key_path'
11
+
12
+ module Dbee
13
+ class Query
14
+ # Abstract representation of the ORDER BY part of a SQL statement.
15
+ class Sorter
16
+ acts_as_hashable
17
+
18
+ module Direction
19
+ ASCENDING = :ascending
20
+ DESCENDING = :descending
21
+ end
22
+ include Direction
23
+
24
+ attr_reader :direction, :key_path
25
+
26
+ def initialize(key_path:, direction: ASCENDING)
27
+ raise ArgumentError, 'key_path is required' if key_path.to_s.empty?
28
+
29
+ @direction = Direction.const_get(direction.to_s.upcase.to_sym)
30
+ @key_path = KeyPath.get(key_path)
31
+
32
+ freeze
33
+ end
34
+
35
+ def descending?
36
+ direction == DESCENDING
37
+ end
38
+
39
+ def ascending?
40
+ !descending?
41
+ end
42
+
43
+ def hash
44
+ "#{key_path}#{direction}".hash
45
+ end
46
+
47
+ def ==(other)
48
+ other.key_path == key_path && other.direction == direction
49
+ end
50
+ alias eql? ==
51
+ end
52
+ end
53
+ end
data/lib/dbee/query.rb ADDED
@@ -0,0 +1,45 @@
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_relative 'query/field'
11
+ require_relative 'query/filters'
12
+ require_relative 'query/sorter'
13
+
14
+ module Dbee
15
+ # This class is an abstration of a simplified SQL expression. In DB terms:
16
+ # - fields are the SELECT
17
+ # - sorters are the ORDER BY
18
+ # - limit is the TAKE
19
+ # - filters are the WHERE
20
+ class Query
21
+ acts_as_hashable
22
+
23
+ attr_reader :fields, :filters, :limit, :sorters
24
+
25
+ def initialize(fields: [], filters: [], limit: nil, sorters: [])
26
+ @fields = Field.array(fields)
27
+ @filters = Filters.array(filters)
28
+ @limit = limit.to_s.empty? ? nil : limit.to_i
29
+ @sorters = Sorter.array(sorters)
30
+
31
+ freeze
32
+ end
33
+
34
+ def ==(other)
35
+ eql?(other)
36
+ end
37
+
38
+ def eql?(other)
39
+ other.fields == fields &&
40
+ other.filters == filters &&
41
+ other.limit == limit &&
42
+ other.sorters == sorters
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,12 @@
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 Dbee
11
+ VERSION = '1.0.0-alpha'
12
+ end
data/lib/dbee.rb ADDED
@@ -0,0 +1,28 @@
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 'acts_as_hashable'
11
+ require 'forwardable'
12
+
13
+ require_relative 'dbee/base'
14
+ require_relative 'dbee/model'
15
+ require_relative 'dbee/query'
16
+ require_relative 'dbee/providers'
17
+
18
+ # Top-level namespace that provides the main public API.
19
+ module Dbee
20
+ class << self
21
+ def sql(model, query, provider)
22
+ model = model.is_a?(Hash) || model.is_a?(Model) ? Model.make(model) : model.to_model
23
+ query = Query.make(query)
24
+
25
+ provider.sql(model, query)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,35 @@
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::Base do
14
+ it 'compiles to Model instance correctly' do
15
+ model_name = 'Theaters, Members, and Movies'
16
+ expected_config = yaml_fixture('models.yaml')[model_name]
17
+
18
+ expected_model = Dbee::Model.make(expected_config)
19
+
20
+ expect(Models::Theaters.to_model).to eq(expected_model)
21
+ end
22
+
23
+ context 'inheritance' do
24
+ specify 'table is honored if set on subclass' do
25
+ expect(Models::A.inherited_table_name).to eq('table_set_to_a')
26
+ expect(Models::B.inherited_table_name).to eq('table_set_to_b')
27
+ end
28
+
29
+ specify 'table is honored if set on parent' do
30
+ expect(Models::C.inherited_table_name).to eq('table_set_to_a')
31
+ expect(Models::D.inherited_table_name).to eq('table_set_to_a')
32
+ expect(Models::E.inherited_table_name).to eq('table_set_to_e')
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,42 @@
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::Model::Constraints::Base 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 'name is required' do
20
+ expect { described_class.new(name: '') }.to raise_error(ArgumentError)
21
+ expect { described_class.new(name: 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) { { name: 'type' } }
28
+
29
+ subject { described_class.new(config) }
30
+
31
+ specify '#hash produces same output as string hash of name' do
32
+ expect(subject.hash).to eq(config[:name].to_s.hash)
33
+ end
34
+
35
+ specify '#== and #eql? compares 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
+ end
@@ -0,0 +1,37 @@
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::Model::Constraints::Reference do
13
+ context '#initialize' do
14
+ specify 'parent is required' do
15
+ expect { described_class.new(name: 'a', parent: '') }.to raise_error(ArgumentError)
16
+ expect { described_class.new(name: 'a', parent: nil) }.to raise_error(ArgumentError)
17
+ expect { described_class.new(name: 'a') }.to raise_error(ArgumentError)
18
+ end
19
+ end
20
+
21
+ context 'equality' do
22
+ let(:config) { { name: 'id', parent: 'patient_id' } }
23
+
24
+ subject { described_class.new(config) }
25
+
26
+ specify '#hash produces same output as concatenated string hash of name and parent' do
27
+ expect(subject.hash).to eq("#{config[:name].hash}#{config[:parent]}".hash)
28
+ end
29
+
30
+ specify '#== and #eql? compare attributes' do
31
+ object2 = described_class.new(config)
32
+
33
+ expect(subject).to eq(object2)
34
+ expect(subject).to eql(object2)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,29 @@
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::Model::Constraints::Static do
13
+ context 'equality' do
14
+ let(:config) { { name: 'type', value: 'general' } }
15
+
16
+ subject { described_class.new(config) }
17
+
18
+ specify '#hash produces same output as concatenated string hash of name and parent' do
19
+ expect(subject.hash).to eq("#{config[:name].hash}#{config[:value]}".hash)
20
+ end
21
+
22
+ specify '#== and #eql? compare attributes' do
23
+ object2 = described_class.new(config)
24
+
25
+ expect(subject).to eq(object2)
26
+ expect(subject).to eql(object2)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,25 @@
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::Model::Constraints do
13
+ CONFIG = { name: :a }.freeze
14
+
15
+ FACTORIES = {
16
+ Dbee::Model::Constraints::Reference => CONFIG.merge(parent: :b, type: :reference),
17
+ Dbee::Model::Constraints::Static => CONFIG.merge(value: :b, type: :static)
18
+ }.freeze
19
+
20
+ FACTORIES.each_pair do |constant, config|
21
+ it "should instantiate #{constant} objects" do
22
+ expect(described_class.make(config)).to be_a(constant)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,113 @@
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::Model do
14
+ describe '#initialize' do
15
+ specify 'name is set properly' do
16
+ config = { name: 'theaters' }
17
+
18
+ model = described_class.make(config)
19
+
20
+ expect(model.name).to eq(config[:name])
21
+ end
22
+
23
+ specify 'table defaults to name' do
24
+ config = { name: 'theaters' }
25
+
26
+ model = described_class.make(config)
27
+
28
+ expect(model.table).to eq(config[:name])
29
+ end
30
+
31
+ specify 'table can be explicitly set' do
32
+ config = { name: 'favorite_comedy_movies', table: 'movies' }
33
+
34
+ model = described_class.make(config)
35
+
36
+ expect(model.table).to eq(config[:table])
37
+ end
38
+
39
+ specify 'models are set properly' do
40
+ config = {
41
+ name: 'theaters',
42
+ models: [
43
+ { name: 'members' },
44
+ { name: 'passes' }
45
+ ]
46
+ }
47
+
48
+ expected_association_names = config[:models].map { |a| a[:name] }
49
+
50
+ model = described_class.make(config)
51
+
52
+ association_names = model.models.map(&:name)
53
+
54
+ expect(association_names).to eq(expected_association_names)
55
+ end
56
+ end
57
+
58
+ describe '#ancestors' do
59
+ let(:yaml_entities) { yaml_fixture('models.yaml') }
60
+
61
+ let(:entity_hash) { yaml_entities['Theaters, Members, and Movies'] }
62
+
63
+ subject { described_class.make(entity_hash) }
64
+
65
+ specify 'returns proper models' do
66
+ members = subject.models.first
67
+
68
+ expected_plan = {
69
+ 'members' => members
70
+ }
71
+
72
+ plan = subject.ancestors(%w[members])
73
+
74
+ expect(plan).to eq(expected_plan)
75
+ end
76
+
77
+ specify 'returns proper multi-level models' do
78
+ members = subject.models.first
79
+ demos = members.models.first
80
+ phone_numbers = demos.models.first
81
+
82
+ expected_plan = {
83
+ 'members' => members,
84
+ 'members.demos' => demos,
85
+ 'members.demos.phone_numbers' => phone_numbers
86
+ }
87
+
88
+ plan = subject.ancestors(%w[members demos phone_numbers])
89
+
90
+ expect(plan).to eq(expected_plan)
91
+ end
92
+
93
+ specify 'equality compares attributes' do
94
+ config = yaml_fixture('models.yaml')['Theaters, Members, and Movies']
95
+
96
+ model1 = described_class.make(config)
97
+ model2 = described_class.make(config)
98
+
99
+ expect(model1).to eq(model2)
100
+ expect(model1).to eql(model2)
101
+ end
102
+ end
103
+
104
+ context 'README examples' do
105
+ specify 'code-first and configuration-first models are equal' do
106
+ config = yaml_fixture('models.yaml')['Readme']
107
+
108
+ config_model = described_class.make(config)
109
+
110
+ expect(config_model).to eq(ReadmeDataModels::Practices.to_model)
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,22 @@
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::Providers::NullProvider do
13
+ specify '#sql returns SELECT NULL' do
14
+ provider = described_class.new
15
+ model = { name: 'something' }
16
+ query = {}
17
+
18
+ actual_sql = provider.sql(model, query)
19
+
20
+ expect(actual_sql).to eq('SELECT NULL')
21
+ end
22
+ end
@@ -0,0 +1,42 @@
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::Field 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', display: 'd' } }
28
+
29
+ subject { described_class.new(config) }
30
+
31
+ specify '#hash produces same output as concatenated string hash of key_path and display' do
32
+ expect(subject.hash).to eq("#{config[:key_path]}#{config[:display]}".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
+ end
@@ -0,0 +1,42 @@
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::Filters::Base 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', value: '123' } }
28
+
29
+ subject { described_class.new(config) }
30
+
31
+ specify '#hash produces same output as concatenated string hash of key_path and value' do
32
+ expect(subject.hash).to eq("#{config[:key_path]}#{config[:value]}".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
+ end
@@ -0,0 +1,33 @@
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::Filters do
13
+ CONFIG = { key_path: 'a.b.c', value: :d }.freeze
14
+
15
+ FACTORIES = {
16
+ Dbee::Query::Filters::Contains => CONFIG.merge(type: :contains),
17
+ Dbee::Query::Filters::Equals => CONFIG.merge(type: :equals),
18
+ Dbee::Query::Filters::GreaterThanOrEqualTo => CONFIG.merge(type: :greater_than_or_equal_to),
19
+ Dbee::Query::Filters::GreaterThan => CONFIG.merge(type: :greater_than),
20
+ Dbee::Query::Filters::LessThanOrEqualTo => CONFIG.merge(type: :less_than_or_equal_to),
21
+ Dbee::Query::Filters::LessThan => CONFIG.merge(type: :less_than),
22
+ Dbee::Query::Filters::NotContain => CONFIG.merge(type: :not_contain),
23
+ Dbee::Query::Filters::NotEquals => CONFIG.merge(type: :not_equals),
24
+ Dbee::Query::Filters::NotStartWith => CONFIG.merge(type: :not_start_with),
25
+ Dbee::Query::Filters::StartsWith => CONFIG.merge(type: :starts_with)
26
+ }.freeze
27
+
28
+ FACTORIES.each_pair do |constant, config|
29
+ it "should instantiate #{constant} objects" do
30
+ expect(described_class.make(config)).to be_a(constant)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,35 @@
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::KeyPath do
13
+ let(:key_path_string) { 'contacts.demographics.first' }
14
+
15
+ subject { described_class.get(key_path_string) }
16
+
17
+ specify '#initialize sets correct values' do
18
+ expect(subject.value).to eq(key_path_string)
19
+ expect(subject.column_name).to eq(key_path_string.split('.').last)
20
+ expect(subject.ancestor_names).to eq(key_path_string.split('.')[0..-2])
21
+ end
22
+
23
+ specify '#hash is same as value.hash' do
24
+ expect(subject.hash).to eq(key_path_string.hash)
25
+ end
26
+
27
+ specify '#to_s is same as value' do
28
+ expect(subject.to_s).to eq(key_path_string)
29
+ end
30
+
31
+ specify 'equality compares to value' do
32
+ expect(subject).to eq(key_path_string)
33
+ expect(subject).to eql(key_path_string)
34
+ end
35
+ end