dbee 2.1.0.pre.alpha → 3.1.0
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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +71 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +6 -17
- data/.tool-versions +1 -0
- data/CHANGELOG.md +21 -1
- data/README.md +154 -62
- data/dbee.gemspec +6 -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/relationships/basic.rb +47 -0
- data/lib/dbee/model/relationships.rb +24 -0
- data/lib/dbee/model.rb +50 -38
- data/lib/dbee/query/field.rb +5 -6
- data/lib/dbee/query.rb +32 -20
- 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/lib/dbee.rb +9 -10
- 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 +56 -62
- 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 +86 -19
- data/.travis.yml +0 -24
@@ -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
|
data/spec/fixtures/models.yaml
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Theaters, Members, and Movies:
|
1
|
+
Theaters, Members, and Movies Tree Based:
|
2
2
|
name: theater
|
3
3
|
table: theaters
|
4
4
|
models:
|
@@ -119,7 +119,217 @@ Theaters, Members, and Movies:
|
|
119
119
|
- type: static
|
120
120
|
name: genre
|
121
121
|
value: comedy
|
122
|
+
|
123
|
+
# Note that since converting from the tree does not have as much context as
|
124
|
+
# converting from the DSL, the resulting graph is a bit different.
|
125
|
+
Theaters, Members, and Movies from Tree:
|
126
|
+
theater:
|
127
|
+
table: theaters
|
128
|
+
relationships:
|
129
|
+
members:
|
130
|
+
constraints:
|
131
|
+
- type: reference
|
132
|
+
parent: id
|
133
|
+
name: tid
|
134
|
+
- type: reference
|
135
|
+
parent: partition
|
136
|
+
name: partition
|
137
|
+
parent_theater:
|
138
|
+
constraints:
|
139
|
+
- type: reference
|
140
|
+
name: id
|
141
|
+
parent: parent_theater_id
|
142
|
+
members:
|
143
|
+
relationships:
|
144
|
+
demos:
|
145
|
+
constraints:
|
146
|
+
- type: reference
|
147
|
+
parent: id
|
148
|
+
name: member_id
|
149
|
+
movies:
|
150
|
+
constraints:
|
151
|
+
- type: reference
|
152
|
+
parent: id
|
153
|
+
name: member_id
|
154
|
+
favorite_comic_movies:
|
155
|
+
constraints:
|
156
|
+
- type: reference
|
157
|
+
parent: id
|
158
|
+
name: member_id
|
159
|
+
- type: static
|
160
|
+
name: genre
|
161
|
+
value: comic
|
162
|
+
favorite_mystery_movies:
|
163
|
+
constraints:
|
164
|
+
- type: reference
|
165
|
+
parent: id
|
166
|
+
name: member_id
|
167
|
+
- type: static
|
168
|
+
name: genre
|
169
|
+
value: mystery
|
170
|
+
favorite_comedy_movies:
|
171
|
+
constraints:
|
172
|
+
- type: reference
|
173
|
+
parent: id
|
174
|
+
name: member_id
|
175
|
+
- type: static
|
176
|
+
name: genre
|
177
|
+
value: comedy
|
178
|
+
demos:
|
179
|
+
table: demographics
|
180
|
+
relationships:
|
181
|
+
phone_numbers:
|
182
|
+
constraints:
|
183
|
+
- type: reference
|
184
|
+
parent: id
|
185
|
+
name: demographic_id
|
186
|
+
phone_numbers:
|
187
|
+
movies:
|
188
|
+
favorite_comic_movies:
|
189
|
+
table: movies
|
190
|
+
favorite_mystery_movies:
|
191
|
+
table: movies
|
192
|
+
favorite_comedy_movies:
|
193
|
+
table: movies
|
194
|
+
parent_theater:
|
195
|
+
table: theaters
|
196
|
+
relationships:
|
197
|
+
members:
|
198
|
+
constraints:
|
199
|
+
- type: reference
|
200
|
+
parent: id
|
201
|
+
name: tid
|
202
|
+
- type: reference
|
203
|
+
parent: partition
|
204
|
+
name: partition
|
205
|
+
|
206
|
+
Theaters, Members, and Movies from DSL:
|
207
|
+
theater:
|
208
|
+
table: theaters
|
209
|
+
relationships:
|
210
|
+
members:
|
211
|
+
model: member
|
212
|
+
constraints:
|
213
|
+
- type: reference
|
214
|
+
parent: id
|
215
|
+
name: tid
|
216
|
+
- type: reference
|
217
|
+
parent: partition
|
218
|
+
name: partition
|
219
|
+
parent_theater:
|
220
|
+
model: theater
|
221
|
+
constraints:
|
222
|
+
- type: reference
|
223
|
+
name: id
|
224
|
+
parent: parent_theater_id
|
225
|
+
member:
|
226
|
+
table: members
|
227
|
+
relationships:
|
228
|
+
movies:
|
229
|
+
model: movie
|
230
|
+
constraints:
|
231
|
+
- type: reference
|
232
|
+
parent: id
|
233
|
+
name: member_id
|
234
|
+
demos:
|
235
|
+
model: demographic
|
236
|
+
constraints:
|
237
|
+
- type: reference
|
238
|
+
parent: id
|
239
|
+
name: member_id
|
240
|
+
favorite_comic_movies:
|
241
|
+
model: movie
|
242
|
+
constraints:
|
243
|
+
- type: reference
|
244
|
+
parent: id
|
245
|
+
name: member_id
|
246
|
+
- type: static
|
247
|
+
name: genre
|
248
|
+
value: comic
|
249
|
+
favorite_mystery_movies:
|
250
|
+
model: movie
|
251
|
+
constraints:
|
252
|
+
- type: reference
|
253
|
+
parent: id
|
254
|
+
name: member_id
|
255
|
+
- type: static
|
256
|
+
name: genre
|
257
|
+
value: mystery
|
258
|
+
favorite_comedy_movies:
|
259
|
+
model: movie
|
260
|
+
constraints:
|
261
|
+
- type: reference
|
262
|
+
parent: id
|
263
|
+
name: member_id
|
264
|
+
- type: static
|
265
|
+
name: genre
|
266
|
+
value: comedy
|
267
|
+
demographic:
|
268
|
+
table: demographics
|
269
|
+
relationships:
|
270
|
+
phone_numbers:
|
271
|
+
model: phone_number
|
272
|
+
constraints:
|
273
|
+
- type: reference
|
274
|
+
parent: id
|
275
|
+
name: demographic_id
|
276
|
+
phone_number:
|
277
|
+
table: phone_numbers
|
278
|
+
movie:
|
279
|
+
table: movies
|
280
|
+
|
122
281
|
Readme:
|
282
|
+
practice:
|
283
|
+
table: practices
|
284
|
+
relationships:
|
285
|
+
patients:
|
286
|
+
model: patient
|
287
|
+
constraints:
|
288
|
+
- type: reference
|
289
|
+
name: practice_id
|
290
|
+
parent: id
|
291
|
+
patient:
|
292
|
+
table: patients
|
293
|
+
relationships:
|
294
|
+
notes:
|
295
|
+
model: note
|
296
|
+
constraints:
|
297
|
+
- type: reference
|
298
|
+
name: patient_id
|
299
|
+
parent: id
|
300
|
+
work_phone_number:
|
301
|
+
model: phone_number
|
302
|
+
constraints:
|
303
|
+
- type: reference
|
304
|
+
name: patient_id
|
305
|
+
parent: id
|
306
|
+
- type: static
|
307
|
+
name: phone_number_type
|
308
|
+
value: work
|
309
|
+
cell_phone_number:
|
310
|
+
model: phone_number
|
311
|
+
constraints:
|
312
|
+
- type: reference
|
313
|
+
name: patient_id
|
314
|
+
parent: id
|
315
|
+
- type: static
|
316
|
+
name: phone_number_type
|
317
|
+
value: cell
|
318
|
+
fax_phone_number:
|
319
|
+
model: phone_number
|
320
|
+
constraints:
|
321
|
+
- type: reference
|
322
|
+
name: patient_id
|
323
|
+
parent: id
|
324
|
+
- type: static
|
325
|
+
name: phone_number_type
|
326
|
+
value: fax
|
327
|
+
note:
|
328
|
+
table: notes
|
329
|
+
phone_number:
|
330
|
+
table: phones
|
331
|
+
|
332
|
+
Readme Tree Based:
|
123
333
|
name: practice
|
124
334
|
table: practices
|
125
335
|
models:
|
@@ -161,63 +371,51 @@ Readme:
|
|
161
371
|
- type: static
|
162
372
|
name: phone_number_type
|
163
373
|
value: fax
|
374
|
+
|
164
375
|
Cycle Example:
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
table: cs
|
186
|
-
models:
|
187
|
-
- name: a
|
188
|
-
table: as
|
189
|
-
- name: d
|
190
|
-
table: ds
|
191
|
-
models:
|
192
|
-
- name: a
|
193
|
-
table: as
|
194
|
-
models:
|
195
|
-
- name: b1
|
196
|
-
table: bs
|
197
|
-
models:
|
198
|
-
- name: c
|
199
|
-
table: cs
|
376
|
+
a:
|
377
|
+
table: as
|
378
|
+
relationships:
|
379
|
+
b1:
|
380
|
+
model: b
|
381
|
+
b2:
|
382
|
+
model: b
|
383
|
+
b:
|
384
|
+
table: bs
|
385
|
+
relationships:
|
386
|
+
c:
|
387
|
+
d:
|
388
|
+
c:
|
389
|
+
table: cs
|
390
|
+
relationships:
|
391
|
+
a:
|
392
|
+
d:
|
393
|
+
table: ds
|
394
|
+
relationships:
|
395
|
+
a:
|
200
396
|
|
201
397
|
Partitioner Example 1:
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
398
|
+
dog:
|
399
|
+
table: animals
|
400
|
+
partitioners:
|
401
|
+
- name: type
|
402
|
+
value: Dog
|
403
|
+
- name: deleted
|
404
|
+
value: false
|
209
405
|
|
210
406
|
Partitioner Example 2:
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
407
|
+
owner:
|
408
|
+
table: owners
|
409
|
+
relationships:
|
410
|
+
dogs:
|
411
|
+
model: dog
|
412
|
+
constraints:
|
413
|
+
- name: owner_id
|
414
|
+
parent: id
|
415
|
+
dog:
|
416
|
+
table: animals
|
417
|
+
partitioners:
|
418
|
+
- name: type
|
419
|
+
value: Dog
|
420
|
+
- name: deleted
|
421
|
+
value: false
|
data/spec/spec_helper.rb
CHANGED
@@ -9,6 +9,13 @@
|
|
9
9
|
|
10
10
|
require 'yaml'
|
11
11
|
require 'pry'
|
12
|
+
require 'pry-byebug'
|
13
|
+
|
14
|
+
RSpec.configure do |config|
|
15
|
+
# Allow for disabling auto focus mode in certain environments like CI to
|
16
|
+
# prevent false positives when only a subset of the suite passes.
|
17
|
+
config.filter_run_when_matching :focus unless ENV['DISABLE_RSPEC_FOCUS'] == 'true'
|
18
|
+
end
|
12
19
|
|
13
20
|
unless ENV['DISABLE_SIMPLECOV'] == 'true'
|
14
21
|
require 'simplecov'
|