dbee 2.1.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +4 -1
- data/.travis.yml +2 -1
- data/CHANGELOG.md +11 -0
- data/README.md +133 -58
- data/dbee.gemspec +5 -2
- data/lib/dbee.rb +9 -10
- data/lib/dbee/base.rb +7 -49
- data/lib/dbee/dsl_schema_builder.rb +86 -0
- data/lib/dbee/key_chain.rb +11 -0
- data/lib/dbee/model.rb +50 -38
- data/lib/dbee/model/relationships.rb +24 -0
- data/lib/dbee/model/relationships/basic.rb +47 -0
- data/lib/dbee/query.rb +4 -0
- data/lib/dbee/query/field.rb +1 -6
- data/lib/dbee/schema.rb +66 -0
- data/lib/dbee/schema_creator.rb +107 -0
- data/lib/dbee/schema_from_tree_based_model.rb +47 -0
- data/lib/dbee/util/make_keyed_by.rb +50 -0
- data/lib/dbee/version.rb +1 -1
- data/spec/dbee/base_spec.rb +9 -72
- data/spec/dbee/constant_resolver_spec.rb +17 -12
- data/spec/dbee/dsl_schema_builder_spec.rb +106 -0
- data/spec/dbee/key_chain_spec.rb +24 -0
- data/spec/dbee/model/constraints_spec.rb +6 -7
- data/spec/dbee/model_spec.rb +62 -59
- data/spec/dbee/query/filters_spec.rb +16 -17
- data/spec/dbee/query_spec.rb +55 -54
- data/spec/dbee/schema_creator_spec.rb +163 -0
- data/spec/dbee/schema_from_tree_based_model_spec.rb +31 -0
- data/spec/dbee/schema_spec.rb +62 -0
- data/spec/dbee_spec.rb +17 -37
- data/spec/fixtures/models.yaml +254 -56
- data/spec/spec_helper.rb +7 -0
- metadata +66 -9
@@ -9,24 +9,23 @@
|
|
9
9
|
|
10
10
|
require 'spec_helper'
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
Dbee::Query::Filters::StartsWith => FILTERS_CONFIG.merge(type: :starts_with)
|
28
|
-
}.freeze
|
12
|
+
FILTERS_CONFIG = { key_path: 'a.b.c', value: :d }.freeze
|
13
|
+
FILTER_FACTORIES = {
|
14
|
+
Dbee::Query::Filters::Contains => FILTERS_CONFIG.merge(type: :contains),
|
15
|
+
Dbee::Query::Filters::Equals => FILTERS_CONFIG.merge(type: :equals),
|
16
|
+
Dbee::Query::Filters::GreaterThanOrEqualTo => FILTERS_CONFIG.merge(
|
17
|
+
type: :greater_than_or_equal_to
|
18
|
+
),
|
19
|
+
Dbee::Query::Filters::GreaterThan => FILTERS_CONFIG.merge(type: :greater_than),
|
20
|
+
Dbee::Query::Filters::LessThanOrEqualTo => FILTERS_CONFIG.merge(type: :less_than_or_equal_to),
|
21
|
+
Dbee::Query::Filters::LessThan => FILTERS_CONFIG.merge(type: :less_than),
|
22
|
+
Dbee::Query::Filters::NotContain => FILTERS_CONFIG.merge(type: :not_contain),
|
23
|
+
Dbee::Query::Filters::NotEquals => FILTERS_CONFIG.merge(type: :not_equals),
|
24
|
+
Dbee::Query::Filters::NotStartWith => FILTERS_CONFIG.merge(type: :not_start_with),
|
25
|
+
Dbee::Query::Filters::StartsWith => FILTERS_CONFIG.merge(type: :starts_with)
|
26
|
+
}.freeze
|
29
27
|
|
28
|
+
describe Dbee::Query::Filters do
|
30
29
|
FILTER_FACTORIES.each_pair do |constant, config|
|
31
30
|
it "should instantiate #{constant} objects" do
|
32
31
|
expect(described_class.make(config)).to be_a(constant)
|
data/spec/dbee/query_spec.rb
CHANGED
@@ -9,9 +9,63 @@
|
|
9
9
|
|
10
10
|
require 'spec_helper'
|
11
11
|
|
12
|
+
README_EXAMPLES = {
|
13
|
+
'Get all practices' => {
|
14
|
+
fields: [
|
15
|
+
{ key_path: 'id' },
|
16
|
+
{ key_path: 'active' },
|
17
|
+
{ key_path: 'name' }
|
18
|
+
]
|
19
|
+
},
|
20
|
+
'Get all practices, limit to 10, and sort by name (descending) then id (ascending)' => {
|
21
|
+
fields: [
|
22
|
+
{ key_path: 'id' },
|
23
|
+
{ key_path: 'active' },
|
24
|
+
{ key_path: 'name' }
|
25
|
+
],
|
26
|
+
sorters: [
|
27
|
+
{ key_path: 'name', direction: :descending },
|
28
|
+
{ key_path: 'id' }
|
29
|
+
],
|
30
|
+
limit: 10
|
31
|
+
},
|
32
|
+
"Get top 5 active practices and patient whose name start with 'Sm':" => {
|
33
|
+
fields: [
|
34
|
+
{ key_path: 'name', display: 'Practice Name' },
|
35
|
+
{ key_path: 'patients.first', display: 'Patient First Name' },
|
36
|
+
{ key_path: 'patients.middle', display: 'Patient Middle Name' },
|
37
|
+
{ key_path: 'patients.last', display: 'Patient Last Name' }
|
38
|
+
],
|
39
|
+
filters: [
|
40
|
+
{ type: :equals, key_path: 'active', value: true },
|
41
|
+
{ type: :starts_with, key_path: 'patients.last', value: 'Sm' }
|
42
|
+
],
|
43
|
+
limit: 5
|
44
|
+
},
|
45
|
+
'Get practice IDs, patient IDs, names, and cell phone numbers that starts with 555' => {
|
46
|
+
fields: [
|
47
|
+
{ key_path: 'id', display: 'Practice ID #' },
|
48
|
+
{ key_path: 'patients.id', display: 'Patient ID #' },
|
49
|
+
{ key_path: 'patients.first', display: 'Patient First Name' },
|
50
|
+
{ key_path: 'patients.middle', display: 'Patient Middle Name' },
|
51
|
+
{ key_path: 'patients.last', display: 'Patient Last Name' },
|
52
|
+
{ key_path: 'patients.cell_phone_numbers.phone_number', display: 'Patient Cell #' }
|
53
|
+
],
|
54
|
+
filters: [
|
55
|
+
{ type: :equals, key_path: 'active', value: true },
|
56
|
+
{
|
57
|
+
type: :starts_with,
|
58
|
+
key_path: 'patients.cell_phone_numbers.phone_number',
|
59
|
+
value: '555'
|
60
|
+
}
|
61
|
+
]
|
62
|
+
}
|
63
|
+
}.freeze
|
64
|
+
|
12
65
|
describe Dbee::Query do
|
13
66
|
let(:config) do
|
14
67
|
{
|
68
|
+
from: 'my_model',
|
15
69
|
fields: [
|
16
70
|
{ key_path: 'matt.nick.sam', display: 'some display' },
|
17
71
|
{ key_path: 'katie' },
|
@@ -116,60 +170,7 @@ describe Dbee::Query do
|
|
116
170
|
end
|
117
171
|
|
118
172
|
context 'README examples' do
|
119
|
-
|
120
|
-
'Get all practices' => {
|
121
|
-
fields: [
|
122
|
-
{ key_path: 'id' },
|
123
|
-
{ key_path: 'active' },
|
124
|
-
{ key_path: 'name' }
|
125
|
-
]
|
126
|
-
},
|
127
|
-
'Get all practices, limit to 10, and sort by name (descending) then id (ascending)' => {
|
128
|
-
fields: [
|
129
|
-
{ key_path: 'id' },
|
130
|
-
{ key_path: 'active' },
|
131
|
-
{ key_path: 'name' }
|
132
|
-
],
|
133
|
-
sorters: [
|
134
|
-
{ key_path: 'name', direction: :descending },
|
135
|
-
{ key_path: 'id' }
|
136
|
-
],
|
137
|
-
limit: 10
|
138
|
-
},
|
139
|
-
"Get top 5 active practices and patient whose name start with 'Sm':" => {
|
140
|
-
fields: [
|
141
|
-
{ key_path: 'name', display: 'Practice Name' },
|
142
|
-
{ key_path: 'patients.first', display: 'Patient First Name' },
|
143
|
-
{ key_path: 'patients.middle', display: 'Patient Middle Name' },
|
144
|
-
{ key_path: 'patients.last', display: 'Patient Last Name' }
|
145
|
-
],
|
146
|
-
filters: [
|
147
|
-
{ type: :equals, key_path: 'active', value: true },
|
148
|
-
{ type: :starts_with, key_path: 'patients.last', value: 'Sm' }
|
149
|
-
],
|
150
|
-
limit: 5
|
151
|
-
},
|
152
|
-
'Get practice IDs, patient IDs, names, and cell phone numbers that starts with 555' => {
|
153
|
-
fields: [
|
154
|
-
{ key_path: 'id', display: 'Practice ID #' },
|
155
|
-
{ key_path: 'patients.id', display: 'Patient ID #' },
|
156
|
-
{ key_path: 'patients.first', display: 'Patient First Name' },
|
157
|
-
{ key_path: 'patients.middle', display: 'Patient Middle Name' },
|
158
|
-
{ key_path: 'patients.last', display: 'Patient Last Name' },
|
159
|
-
{ key_path: 'patients.cell_phone_numbers.phone_number', display: 'Patient Cell #' }
|
160
|
-
],
|
161
|
-
filters: [
|
162
|
-
{ type: :equals, key_path: 'active', value: true },
|
163
|
-
{
|
164
|
-
type: :starts_with,
|
165
|
-
key_path: 'patients.cell_phone_numbers.phone_number',
|
166
|
-
value: '555'
|
167
|
-
}
|
168
|
-
]
|
169
|
-
}
|
170
|
-
}.freeze
|
171
|
-
|
172
|
-
EXAMPLES.each_pair do |name, query|
|
173
|
+
README_EXAMPLES.each_pair do |name, query|
|
173
174
|
specify name do
|
174
175
|
expect(described_class.make(query)).to be_a(described_class)
|
175
176
|
end
|
@@ -0,0 +1,163 @@
|
|
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::SchemaCreator do
|
14
|
+
let(:model_hash_graph) do
|
15
|
+
{
|
16
|
+
'model1' => {
|
17
|
+
relationships: {
|
18
|
+
model2: {
|
19
|
+
constraints: [
|
20
|
+
{
|
21
|
+
type: 'reference',
|
22
|
+
parent: 'id',
|
23
|
+
name: 'model1_id'
|
24
|
+
}
|
25
|
+
]
|
26
|
+
}
|
27
|
+
}
|
28
|
+
},
|
29
|
+
'model2' => nil
|
30
|
+
}
|
31
|
+
end
|
32
|
+
let(:schema) { Dbee::Schema.new(model_hash_graph) }
|
33
|
+
|
34
|
+
let(:model_hash_tree) do
|
35
|
+
{
|
36
|
+
name: 'model1',
|
37
|
+
models: [
|
38
|
+
{
|
39
|
+
name: 'model2',
|
40
|
+
constraints: [
|
41
|
+
{
|
42
|
+
type: 'reference',
|
43
|
+
parent: 'id',
|
44
|
+
name: 'model1_id'
|
45
|
+
}
|
46
|
+
]
|
47
|
+
}
|
48
|
+
]
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
let(:model_tree) { Dbee::Model.make(model_hash_tree) }
|
53
|
+
|
54
|
+
let(:query_hash) do
|
55
|
+
{
|
56
|
+
from: 'model1',
|
57
|
+
fields: [
|
58
|
+
{ key_path: :a }
|
59
|
+
]
|
60
|
+
}
|
61
|
+
end
|
62
|
+
let(:query) { Dbee::Query.make(query_hash) }
|
63
|
+
|
64
|
+
let(:query_hash_no_from) { query_hash.slice(:fields) }
|
65
|
+
let(:query_no_from) { Dbee::Query.make(query_hash_no_from) }
|
66
|
+
|
67
|
+
describe 'query parsing' do
|
68
|
+
it 'passes through Dbee::Query instances' do
|
69
|
+
expect(described_class.new(schema, query).query).to eq query
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'creates a Dbee::Query from a query hash' do
|
73
|
+
expect(described_class.new(schema, query_hash).query).to eq query
|
74
|
+
end
|
75
|
+
|
76
|
+
describe 'the "from" field' do
|
77
|
+
it 'raises an error when nil' do
|
78
|
+
expect do
|
79
|
+
described_class.new(schema, query_hash_no_from)
|
80
|
+
end.to raise_error(ArgumentError, 'query requires a from model name')
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'raises an error when the empty string' do
|
84
|
+
expect do
|
85
|
+
described_class.new(schema, query_hash_no_from.merge(from: ''))
|
86
|
+
end.to raise_error(ArgumentError, 'query requires a from model name')
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe 'tree based models' do
|
92
|
+
it 'creates a schema from a Dbee::Model' do
|
93
|
+
expect(described_class.new(model_tree, query).schema).to eq schema
|
94
|
+
end
|
95
|
+
|
96
|
+
describe 'hash detection' do
|
97
|
+
it 'creates a schema from a hash model' do
|
98
|
+
expect(described_class.new(model_hash_tree, query).schema).to eq schema
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'creates a schema from a minimal hash model with no child models' do
|
102
|
+
minimal_tree_hash = { name: :practice }
|
103
|
+
minimal_schema = Dbee::Schema.new(practice: nil)
|
104
|
+
|
105
|
+
expect(described_class.new(minimal_tree_hash, {}).schema).to eq minimal_schema
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe 'query "from" field' do
|
110
|
+
it 'is set using name of the root model of the tree' do
|
111
|
+
expect(described_class.new(model_tree, query_no_from).query).to eq query
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'raises an error the query "from" does not equal the root model name' do
|
115
|
+
query_hash_different_from = query_hash_no_from.merge(from: :bogus_model)
|
116
|
+
|
117
|
+
expect do
|
118
|
+
described_class.new(model_tree, query_hash_different_from)
|
119
|
+
end.to raise_error(
|
120
|
+
ArgumentError,
|
121
|
+
"expected from model to be 'model1' but got 'bogus_model'"
|
122
|
+
)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe 'graph based models' do
|
128
|
+
it 'creates a schema from a hash schema' do
|
129
|
+
expect(described_class.new(model_hash_graph, query).schema).to eq schema
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'passes through Dbee::Schema instances' do
|
133
|
+
expect(described_class.new(schema, query).schema).to eq schema
|
134
|
+
end
|
135
|
+
|
136
|
+
describe 'when given a Dbee::Base class' do
|
137
|
+
let(:dsl_model_class) { PartitionerExamples::Dog }
|
138
|
+
|
139
|
+
it 'creates a schema' do
|
140
|
+
expected_config = yaml_fixture('models.yaml')['Partitioner Example 1']
|
141
|
+
expected_schema = Dbee::Schema.new(expected_config)
|
142
|
+
dog_query = Dbee::Query.make(query_hash_no_from.merge(from: :dog))
|
143
|
+
|
144
|
+
expect(described_class.new(dsl_model_class, dog_query).schema).to eq expected_schema
|
145
|
+
end
|
146
|
+
|
147
|
+
it "can infer the query's 'from' field" do
|
148
|
+
expect(described_class.new(dsl_model_class, query_no_from).query.from).to eq 'dog'
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'raises an error the query "from" does not equal the DSL model name' do
|
152
|
+
cat_query = Dbee::Query.make(query_hash_no_from.merge(from: :cat))
|
153
|
+
|
154
|
+
expect do
|
155
|
+
described_class.new(dsl_model_class, cat_query)
|
156
|
+
end.to raise_error(
|
157
|
+
ArgumentError,
|
158
|
+
"expected from model to be 'dog' but got 'cat'"
|
159
|
+
)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,31 @@
|
|
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::SchemaFromTreeBasedModel do
|
14
|
+
let(:tree_config) do
|
15
|
+
Dbee::Model.make(yaml_fixture('models.yaml')['Theaters, Members, and Movies Tree Based'])
|
16
|
+
end
|
17
|
+
let(:schema_config) do
|
18
|
+
yaml_fixture('models.yaml')['Theaters, Members, and Movies from Tree']
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'converts the theaters model' do
|
22
|
+
expected_schema = Dbee::Schema.new(schema_config)
|
23
|
+
expect(described_class.convert(tree_config)).to eq expected_schema
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'does not raise any errors when converting the readme model' do
|
27
|
+
tree_config = Dbee::Model.make(yaml_fixture('models.yaml')['Readme Tree Based'])
|
28
|
+
|
29
|
+
expect { described_class.convert(tree_config) }.not_to raise_error
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,62 @@
|
|
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_relative '../fixtures/models'
|
12
|
+
|
13
|
+
describe Dbee::Schema do
|
14
|
+
def make_model(model_name)
|
15
|
+
raise "no model named '#{model_name}'" unless schema_config.key?(model_name)
|
16
|
+
|
17
|
+
Dbee::Model.make((schema_config[model_name] || {}).merge('name' => model_name))
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:model_name) do
|
21
|
+
'Theaters, Members, and Movies from DSL'
|
22
|
+
end
|
23
|
+
let(:schema_config) { yaml_fixture('models.yaml')[model_name] }
|
24
|
+
|
25
|
+
let(:demographics_model) { make_model('demographic') }
|
26
|
+
let(:members_model) { make_model('member') }
|
27
|
+
let(:movies_model) { make_model('movie') }
|
28
|
+
let(:phone_numbers_model) { make_model('phone_number') }
|
29
|
+
let(:theaters_model) { make_model('theater') }
|
30
|
+
|
31
|
+
let(:subject) { described_class.new(schema_config) }
|
32
|
+
|
33
|
+
describe '#expand_query_path' do
|
34
|
+
specify 'one model case' do
|
35
|
+
expect(subject.expand_query_path(members_model, Dbee::KeyPath.new('id'))).to eq []
|
36
|
+
end
|
37
|
+
|
38
|
+
specify 'two model case' do
|
39
|
+
expected_path = [[members_model.relationship_for_name('movies'), movies_model]]
|
40
|
+
expect(
|
41
|
+
subject.expand_query_path(members_model, Dbee::KeyPath.new('movies.id'))
|
42
|
+
).to eq expected_path
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'traverses aliased models' do
|
46
|
+
expected_path = [
|
47
|
+
[members_model.relationship_for_name('demos'), demographics_model],
|
48
|
+
[demographics_model.relationship_for_name('phone_numbers'), phone_numbers_model]
|
49
|
+
]
|
50
|
+
|
51
|
+
expect(
|
52
|
+
subject.expand_query_path(members_model, Dbee::KeyPath.new('demos.phone_numbers.id'))
|
53
|
+
).to eq expected_path
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'raises an error given an unknown relationship' do
|
57
|
+
expect do
|
58
|
+
subject.expand_query_path(theaters_model, Dbee::KeyPath.new('demographics.id'))
|
59
|
+
end.to raise_error("model 'theater' does not have a 'demographics' relationship")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/spec/dbee_spec.rb
CHANGED
@@ -13,59 +13,39 @@ require 'fixtures/models'
|
|
13
13
|
describe Dbee do
|
14
14
|
describe '#sql' do
|
15
15
|
let(:provider) { Dbee::Providers::NullProvider.new }
|
16
|
-
|
17
|
-
let(:model_hash) do
|
18
|
-
{
|
19
|
-
name: 'something'
|
20
|
-
}
|
21
|
-
end
|
22
|
-
|
23
|
-
let(:model) { Dbee::Model.make(model_hash) }
|
24
|
-
|
25
16
|
let(:query_hash) do
|
26
17
|
{
|
18
|
+
from: 'my_model',
|
27
19
|
fields: [
|
28
20
|
{ key_path: :a }
|
29
21
|
]
|
30
22
|
}
|
31
23
|
end
|
32
|
-
|
33
24
|
let(:query) { Dbee::Query.make(query_hash) }
|
25
|
+
let(:schema) { Dbee::Schema.new({}) }
|
34
26
|
|
35
|
-
it 'accepts a hash
|
36
|
-
expect(provider).to receive(:sql).with(
|
37
|
-
|
38
|
-
described_class.sql(model_hash, query, provider)
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'accepts a Dbee::Model instance as a model and passes a Model instance to provider#sql' do
|
42
|
-
expect(provider).to receive(:sql).with(model, query)
|
27
|
+
it 'accepts a query hash and a Schema and passes them into provider#sql' do
|
28
|
+
expect(provider).to receive(:sql).with(schema, query)
|
43
29
|
|
44
|
-
described_class.sql(
|
30
|
+
described_class.sql(schema, query_hash, provider)
|
45
31
|
end
|
46
32
|
|
47
|
-
it '
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
described_class.sql(model_constant, query, provider)
|
33
|
+
it 'does not allow a nil schema' do
|
34
|
+
expect do
|
35
|
+
described_class.sql(nil, query, provider)
|
36
|
+
end.to raise_error ArgumentError, /schema or model is required/
|
53
37
|
end
|
54
38
|
|
55
|
-
it '
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
described_class.sql(model, query, provider)
|
39
|
+
it 'does not allow a nil query' do
|
40
|
+
expect do
|
41
|
+
described_class.sql(schema, nil, provider)
|
42
|
+
end.to raise_error ArgumentError, /query is required/
|
61
43
|
end
|
62
44
|
|
63
|
-
it '
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
described_class.sql(model, query_hash, provider)
|
45
|
+
it 'does not allow a nil provider' do
|
46
|
+
expect do
|
47
|
+
described_class.sql(schema, query, nil)
|
48
|
+
end.to raise_error ArgumentError, /provider is required/
|
69
49
|
end
|
70
50
|
end
|
71
51
|
end
|