dbee 1.0.0.pre.alpha

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