consistency_fail 0.3.3 → 0.3.4
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 +5 -13
- data/.rspec +1 -0
- data/bin/consistency_fail +1 -31
- data/consistency_fail.gemspec +2 -1
- data/lib/consistency_fail.rb +38 -0
- data/lib/consistency_fail/index.rb +18 -0
- data/lib/consistency_fail/introspectors/has_one.rb +1 -1
- data/lib/consistency_fail/introspectors/polymorphic.rb +1 -2
- data/lib/consistency_fail/introspectors/validates_uniqueness_of.rb +1 -0
- data/lib/consistency_fail/models.rb +0 -1
- data/lib/consistency_fail/version.rb +1 -1
- data/spec/index_spec.rb +37 -18
- data/spec/introspectors/has_one_spec.rb +14 -89
- data/spec/introspectors/polymorphic_spec.rb +15 -66
- data/spec/introspectors/table_data_spec.rb +47 -36
- data/spec/introspectors/validates_uniqueness_of_spec.rb +47 -72
- data/spec/models_spec.rb +2 -3
- data/spec/reporter_spec.rb +88 -49
- data/spec/spec_helper.rb +11 -10
- data/spec/support/active_record.rb +1 -0
- data/spec/support/models/correct_account.rb +3 -0
- data/spec/support/models/correct_address.rb +3 -0
- data/spec/support/models/correct_attachment.rb +5 -0
- data/spec/support/models/correct_person.rb +3 -0
- data/spec/support/models/correct_post.rb +3 -0
- data/spec/support/models/correct_user.rb +7 -0
- data/spec/support/models/correct_user/credential.rb +3 -0
- data/spec/support/models/correct_user/phone.rb +4 -0
- data/spec/support/models/new_correct_person.rb +7 -0
- data/spec/support/models/nonexistent.rb +2 -0
- data/spec/support/models/wrong_account.rb +3 -0
- data/spec/support/models/wrong_address.rb +5 -0
- data/spec/support/models/wrong_attachment.rb +3 -0
- data/spec/support/models/wrong_business.rb +3 -0
- data/spec/support/models/wrong_person.rb +3 -0
- data/spec/support/models/wrong_post.rb +3 -0
- data/spec/support/models/wrong_user.rb +3 -0
- data/spec/support/schema.rb +121 -0
- metadata +68 -24
@@ -1,52 +1,63 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'consistency_fail/introspectors/table_data'
|
3
|
-
|
4
1
|
describe ConsistencyFail::Introspectors::TableData do
|
2
|
+
|
5
3
|
describe "finding unique indexes" do
|
6
4
|
it "finds none when the table does not exist" do
|
7
|
-
|
8
|
-
|
9
|
-
expect(subject.unique_indexes(model)).to eq([])
|
5
|
+
expect(subject.unique_indexes(Nonexistent)).to be_empty
|
10
6
|
end
|
11
7
|
|
12
8
|
it "gets one" do
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
9
|
+
index = ConsistencyFail::Index.new(
|
10
|
+
CorrectAccount,
|
11
|
+
CorrectAccount.table_name,
|
12
|
+
["email"]
|
13
|
+
)
|
14
|
+
|
15
|
+
expect(
|
16
|
+
ConsistencyFail::Introspectors::TableData.new.unique_indexes_by_table(
|
17
|
+
CorrectAccount,
|
18
|
+
ActiveRecord::Base.connection,
|
19
|
+
CorrectAccount.table_name
|
20
|
+
)
|
21
|
+
).to eq [index]
|
22
22
|
end
|
23
23
|
|
24
24
|
it "doesn't get non-unique indexes" do
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
expect(subject.unique_indexes(model)).to eq([])
|
25
|
+
expect(
|
26
|
+
ConsistencyFail::Introspectors::TableData.new.unique_indexes_by_table(
|
27
|
+
WrongAddress,
|
28
|
+
ActiveRecord::Base.connection,
|
29
|
+
WrongAddress.table_name
|
30
|
+
)
|
31
|
+
).to be_empty
|
33
32
|
end
|
34
33
|
|
35
34
|
it "gets multiple unique indexes" do
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
35
|
+
indexes = [
|
36
|
+
ConsistencyFail::Index.new(
|
37
|
+
CorrectAttachment,
|
38
|
+
CorrectAttachment.table_name,
|
39
|
+
["name"]
|
40
|
+
),
|
41
|
+
ConsistencyFail::Index.new(
|
42
|
+
CorrectAttachment,
|
43
|
+
CorrectAttachment.table_name,
|
44
|
+
["attachable_id", "attachable_type"]
|
45
|
+
),
|
46
|
+
ConsistencyFail::Index.new(
|
47
|
+
CorrectAttachment,
|
48
|
+
CorrectAttachment.table_name,
|
49
|
+
["name", "attachable_id", "attachable_type"]
|
50
|
+
)
|
51
|
+
]
|
52
|
+
|
53
|
+
expect(
|
54
|
+
ConsistencyFail::Introspectors::TableData.new.unique_indexes_by_table(
|
55
|
+
CorrectAttachment,
|
56
|
+
ActiveRecord::Base.connection,
|
57
|
+
CorrectAttachment.table_name
|
58
|
+
)
|
59
|
+
).to eq indexes
|
48
60
|
end
|
49
61
|
end
|
50
62
|
|
51
63
|
end
|
52
|
-
|
@@ -1,93 +1,68 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'consistency_fail/introspectors/validates_uniqueness_of'
|
3
|
-
|
4
1
|
describe ConsistencyFail::Introspectors::ValidatesUniquenessOf do
|
5
|
-
def introspector(model)
|
6
|
-
ConsistencyFail::Introspectors::ValidatesUniquenessOf.new(model)
|
7
|
-
end
|
8
|
-
|
9
|
-
describe "instances of validates_uniqueness_of" do
|
10
|
-
it "finds none" do
|
11
|
-
model = fake_ar_model("User")
|
12
|
-
allow(model).to receive(:validators).and_return([])
|
13
|
-
|
14
|
-
expect(subject.instances(model)).to eq([])
|
15
|
-
end
|
16
|
-
|
17
|
-
it "finds one" do
|
18
|
-
model = fake_ar_model("User")
|
19
|
-
validation = double("validation", :class => ActiveRecord::Validations::UniquenessValidator)
|
20
|
-
allow(model).to receive(:validators).and_return([validation])
|
21
|
-
|
22
|
-
expect(subject.instances(model)).to eq([validation])
|
23
|
-
end
|
24
|
-
|
25
|
-
it "finds other validations, but not uniqueness" do
|
26
|
-
model = fake_ar_model("User")
|
27
|
-
validation = double("validation", :class => ActiveModel::Validations::FormatValidator)
|
28
|
-
allow(model).to receive(:validators).and_return([validation])
|
29
|
-
|
30
|
-
expect(subject.instances(model)).to eq([])
|
31
|
-
end
|
32
|
-
end
|
33
2
|
|
34
3
|
describe "finding missing indexes" do
|
35
|
-
before do
|
36
|
-
@validation = double("validation", :class => ActiveRecord::Validations::UniquenessValidator)
|
37
|
-
@model = fake_ar_model("User", :table_exists? => true,
|
38
|
-
:table_name => "users",
|
39
|
-
:validators => [@validation])
|
40
|
-
end
|
41
|
-
|
42
4
|
it "finds one" do
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
5
|
+
indexes = subject.missing_indexes(WrongAccount)
|
6
|
+
|
7
|
+
expect(indexes).to eq([
|
8
|
+
ConsistencyFail::Index.new(
|
9
|
+
WrongAccount,
|
10
|
+
WrongAccount.table_name,
|
11
|
+
["email"]
|
12
|
+
)
|
13
|
+
])
|
48
14
|
end
|
49
15
|
|
50
16
|
it "finds one where the validation has scoped columns" do
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
allow(@model).to receive_message_chain(:connection, :indexes).with("users").and_return([])
|
61
|
-
|
62
|
-
indexes = subject.missing_indexes(@model)
|
63
|
-
expect(indexes).to eq([ConsistencyFail::Index.new(double('model'), "users", ["email", "city", "state"])])
|
17
|
+
indexes = subject.missing_indexes(WrongBusiness)
|
18
|
+
|
19
|
+
expect(indexes).to eq([
|
20
|
+
ConsistencyFail::Index.new(
|
21
|
+
WrongBusiness,
|
22
|
+
WrongBusiness.table_name,
|
23
|
+
["name", "city", "state"]
|
24
|
+
)
|
25
|
+
])
|
64
26
|
end
|
65
27
|
|
66
28
|
it "finds two where there are multiple attributes" do
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
29
|
+
indexes = subject.missing_indexes(WrongPerson)
|
30
|
+
|
31
|
+
expect(indexes).to eq(
|
32
|
+
[
|
33
|
+
ConsistencyFail::Index.new(
|
34
|
+
WrongPerson,
|
35
|
+
WrongPerson.table_name,
|
36
|
+
["email", "city", "state"]
|
37
|
+
),
|
38
|
+
ConsistencyFail::Index.new(
|
39
|
+
WrongPerson,
|
40
|
+
WrongPerson.table_name,
|
41
|
+
["name", "city", "state"]
|
42
|
+
)
|
43
|
+
]
|
44
|
+
)
|
73
45
|
end
|
74
46
|
|
75
47
|
it "finds none when they're already in place" do
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
48
|
+
expect(subject.missing_indexes(CorrectAccount)).to be_empty
|
49
|
+
end
|
50
|
+
|
51
|
+
it "finds none even if scoped by association" do
|
52
|
+
expect(subject.missing_indexes(CorrectAddress)).to be_empty
|
53
|
+
end
|
80
54
|
|
81
|
-
|
55
|
+
it "finds none even if scoped by polymorphic association" do
|
56
|
+
expect(subject.missing_indexes(CorrectAttachment)).to be_empty
|
82
57
|
end
|
83
58
|
|
84
59
|
it "finds none when indexes are there but in a different order" do
|
85
|
-
|
86
|
-
|
87
|
-
allow(@model).to receive_message_chain(:connection, :indexes).with("users").
|
88
|
-
and_return([index])
|
60
|
+
expect(subject.missing_indexes(CorrectPerson)).to be_empty
|
61
|
+
end
|
89
62
|
|
90
|
-
|
63
|
+
it "finds none when the model is an SQL view" do
|
64
|
+
expect(subject.missing_indexes(NewCorrectPerson)).to be_empty
|
91
65
|
end
|
92
66
|
end
|
67
|
+
|
93
68
|
end
|
data/spec/models_spec.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'consistency_fail/models'
|
3
|
-
|
4
1
|
describe ConsistencyFail::Models do
|
2
|
+
|
5
3
|
def models(load_path)
|
6
4
|
ConsistencyFail::Models.new(load_path)
|
7
5
|
end
|
@@ -46,4 +44,5 @@ describe ConsistencyFail::Models do
|
|
46
44
|
|
47
45
|
expect(models([]).all).to eq([model_a, model_c, model_b])
|
48
46
|
end
|
47
|
+
|
49
48
|
end
|
data/spec/reporter_spec.rb
CHANGED
@@ -1,90 +1,129 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'consistency_fail/reporter'
|
3
|
-
require 'consistency_fail/index'
|
4
|
-
|
5
1
|
describe ConsistencyFail::Reporter do
|
6
|
-
|
7
|
-
@real_out = $stdout
|
8
|
-
@fake_out = StringIO.new
|
9
|
-
$stdout = @fake_out
|
10
|
-
end
|
11
|
-
after(:each) do
|
12
|
-
$stdout = @real_out
|
13
|
-
end
|
14
|
-
|
2
|
+
|
15
3
|
context "validates_uniqueness_of" do
|
16
4
|
it "says everything's good" do
|
17
|
-
|
18
|
-
|
19
|
-
|
5
|
+
expect {
|
6
|
+
subject.report_validates_uniqueness_problems([])
|
7
|
+
}.to output(/Hooray!/).to_stdout
|
20
8
|
end
|
21
9
|
|
22
10
|
it "shows a missing single-column index on a single model" do
|
23
|
-
missing_indexes = [
|
24
|
-
|
25
|
-
|
11
|
+
missing_indexes = [
|
12
|
+
ConsistencyFail::Index.new(
|
13
|
+
WrongAccount,
|
14
|
+
WrongAccount.table_name,
|
15
|
+
["email"]
|
16
|
+
)
|
17
|
+
]
|
26
18
|
|
27
|
-
expect
|
19
|
+
expect {
|
20
|
+
subject.report_validates_uniqueness_problems(
|
21
|
+
WrongAccount => missing_indexes
|
22
|
+
)
|
23
|
+
}.to output(/wrong_accounts\s+\(email\)/).to_stdout
|
28
24
|
end
|
29
25
|
|
30
26
|
it "shows a missing multiple-column index on a single model" do
|
31
|
-
missing_indexes = [
|
32
|
-
|
33
|
-
|
27
|
+
missing_indexes = [
|
28
|
+
ConsistencyFail::Index.new(
|
29
|
+
WrongBusiness,
|
30
|
+
WrongBusiness.table_name,
|
31
|
+
["name", "city", "state"]
|
32
|
+
)
|
33
|
+
]
|
34
34
|
|
35
|
-
expect
|
35
|
+
expect {
|
36
|
+
subject.report_validates_uniqueness_problems(
|
37
|
+
WrongBusiness => missing_indexes
|
38
|
+
)
|
39
|
+
}.to output(/wrong_businesses\s+\(name, city, state\)/).to_stdout
|
36
40
|
end
|
37
41
|
|
38
42
|
context "with problems on multiple models" do
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
def report
|
44
|
+
missing_indices = {
|
45
|
+
WrongAccount => [
|
46
|
+
ConsistencyFail::Index.new(
|
47
|
+
WrongAccount,
|
48
|
+
WrongAccount.table_name,
|
49
|
+
["email"]
|
50
|
+
)
|
51
|
+
],
|
52
|
+
WrongBusiness => [
|
53
|
+
ConsistencyFail::Index.new(
|
54
|
+
WrongBusiness,
|
55
|
+
WrongBusiness.table_name,
|
56
|
+
["name", "city", "state"]
|
57
|
+
)
|
58
|
+
]
|
59
|
+
}
|
60
|
+
|
61
|
+
subject.report_validates_uniqueness_problems(missing_indices)
|
46
62
|
end
|
47
63
|
|
48
64
|
it "shows all problems" do
|
49
|
-
expect
|
50
|
-
expect
|
65
|
+
expect { report }.to output(/wrong_accounts\s+\(email\)/).to_stdout
|
66
|
+
expect { report }.to output(
|
67
|
+
/wrong_businesses\s+\(name, city, state\)/
|
68
|
+
).to_stdout
|
51
69
|
end
|
52
70
|
|
53
71
|
it "orders the models alphabetically" do
|
54
|
-
expect
|
72
|
+
expect { report }.to output(/
|
73
|
+
wrong_accounts\s+\(email\)
|
74
|
+
(\s|\S)*
|
75
|
+
wrong_businesses\s+\(name,\scity,\sstate\)
|
76
|
+
/x).to_stdout
|
55
77
|
end
|
56
78
|
end
|
57
79
|
end
|
58
80
|
|
59
81
|
context "has_one" do
|
60
82
|
it "says everything's good" do
|
61
|
-
|
62
|
-
|
63
|
-
|
83
|
+
expect {
|
84
|
+
subject.report_has_one_problems([])
|
85
|
+
}.to output(/Hooray!/).to_stdout
|
64
86
|
end
|
65
87
|
|
66
88
|
it "shows a missing single-column index on a single model" do
|
67
|
-
missing_indexes = [
|
68
|
-
|
69
|
-
|
89
|
+
missing_indexes = [
|
90
|
+
ConsistencyFail::Index.new(
|
91
|
+
WrongAddress,
|
92
|
+
WrongAddress.table_name,
|
93
|
+
["wrong_user_id"]
|
94
|
+
)
|
95
|
+
]
|
70
96
|
|
71
|
-
expect
|
97
|
+
expect {
|
98
|
+
subject.report_has_one_problems(WrongAddress => missing_indexes)
|
99
|
+
}.to output(/wrong_addresses\s+\(wrong_user_id\)/).to_stdout
|
72
100
|
end
|
73
101
|
end
|
74
102
|
|
75
103
|
context "polymorphic" do
|
76
104
|
it "says everything's good" do
|
77
|
-
|
78
|
-
|
79
|
-
|
105
|
+
expect {
|
106
|
+
subject.report_polymorphic_problems([])
|
107
|
+
}.to output(/Hooray!/).to_stdout
|
80
108
|
end
|
81
109
|
|
82
110
|
it "shows a missing compound index on a single model" do
|
83
|
-
missing_indexes = [
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
111
|
+
missing_indexes = [
|
112
|
+
ConsistencyFail::Index.new(
|
113
|
+
WrongAttachment,
|
114
|
+
WrongAttachment.table_name,
|
115
|
+
["attachable_type", "attachable_id"]
|
116
|
+
)
|
117
|
+
]
|
118
|
+
|
119
|
+
expect {
|
120
|
+
subject.report_polymorphic_problems(WrongAttachment => missing_indexes)
|
121
|
+
}.to(
|
122
|
+
output(
|
123
|
+
/wrong_attachments\s+\(attachable_type, attachable_id\)/
|
124
|
+
).to_stdout
|
125
|
+
)
|
88
126
|
end
|
89
127
|
end
|
128
|
+
|
90
129
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,13 +1,14 @@
|
|
1
|
-
|
2
|
-
$:<< File.expand_path('../../lib', __FILE__)
|
1
|
+
require 'bundler/setup'
|
3
2
|
|
4
|
-
require
|
3
|
+
Bundler.require(:default, :test)
|
5
4
|
|
6
|
-
|
7
|
-
double("AR model: #{name}", options.merge(:name => name))
|
8
|
-
end
|
9
|
-
|
10
|
-
def fake_index_on(columns, options = {})
|
11
|
-
double("index on #{columns.inspect}", options.merge(:columns => columns))
|
12
|
-
end
|
5
|
+
Dir['./spec/support/**/*.rb'].each { |file| require file }
|
13
6
|
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.around do |example|
|
9
|
+
ActiveRecord::Base.transaction do
|
10
|
+
example.run
|
11
|
+
raise ActiveRecord::Rollback
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|