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