active_sanity 0.1.0 → 0.1.1
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.
- data/Rakefile +14 -0
- data/features/check_sanity.feature +3 -3
- data/features/check_sanity_with_db_storage.feature +5 -5
- data/features/step_definitions/rails_app.rb +8 -8
- data/features/support/env.rb +12 -9
- data/lib/active_sanity/checker.rb +53 -12
- data/lib/active_sanity/version.rb +1 -1
- data/test/rails_template.rb +18 -8
- metadata +4 -4
data/Rakefile
CHANGED
@@ -1,2 +1,16 @@
|
|
1
1
|
require 'bundler'
|
2
2
|
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
task :default => :features
|
5
|
+
|
6
|
+
desc "Run features"
|
7
|
+
task :features do
|
8
|
+
raise "Failed!" unless system('bundle exec cucumber features')
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Clean test rails app"
|
12
|
+
task :clean do
|
13
|
+
if system('rm -r test/rails_app')
|
14
|
+
puts "test/rails_app deleted successfully"
|
15
|
+
end
|
16
|
+
end
|
@@ -9,7 +9,7 @@ Feature: Check sanity
|
|
9
9
|
|
10
10
|
Scenario: Check sanity on empty database
|
11
11
|
When I run "rake db:check_sanity"
|
12
|
-
Then I should see "Checking the following models:
|
12
|
+
Then I should see "Checking the following models: Category, InvalidRecord, Post, User"
|
13
13
|
Then I should not see any invalid records
|
14
14
|
|
15
15
|
Scenario: Check sanity on database with valid records
|
@@ -19,8 +19,8 @@ Feature: Check sanity
|
|
19
19
|
|
20
20
|
Scenario: Check sanity on database with invalid records
|
21
21
|
Given the database contains a few valid records
|
22
|
-
And the first
|
22
|
+
And the first author's username is empty and the first post category_id is nil
|
23
23
|
When I run "rake db:check_sanity"
|
24
24
|
Then I should see the following invalid records:
|
25
|
-
| User | 1 | {:username=>["can't be blank", "is too short (minimum is 3 characters)"]} |
|
25
|
+
| User | 1 | {:username=>["can't be blank", "is too short (minimum is 3 characters)", "can't be blank", "can't be blank", "is too short (minimum is 3 characters)"]} |
|
26
26
|
| Post | 1 | {:category=>["can't be blank"]} |
|
@@ -9,7 +9,7 @@ Feature: Check sanity with db storage
|
|
9
9
|
|
10
10
|
Scenario: Check sanity on empty database
|
11
11
|
When I run "rake db:check_sanity"
|
12
|
-
Then I should see "Checking the following models:
|
12
|
+
Then I should see "Checking the following models: Category, InvalidRecord, Post, User"
|
13
13
|
Then the table "invalid_records" should be empty
|
14
14
|
|
15
15
|
Scenario: Check sanity on database with valid records
|
@@ -19,7 +19,7 @@ Feature: Check sanity with db storage
|
|
19
19
|
|
20
20
|
Scenario: Check sanity on database with invalid records
|
21
21
|
Given the database contains a few valid records
|
22
|
-
And the first
|
22
|
+
And the first author's username is empty and the first post category_id is nil
|
23
23
|
When I run "rake db:check_sanity"
|
24
24
|
Then the table "invalid_records" should contain:
|
25
25
|
| User | 1 | {:username=>["is too short (minimum is 3 characters)"]} |
|
@@ -27,13 +27,13 @@ Feature: Check sanity with db storage
|
|
27
27
|
|
28
28
|
Scenario: Check sanity on database with invalid records now valid
|
29
29
|
Given the database contains a few valid records
|
30
|
-
And the first
|
30
|
+
And the first author's username is empty and the first post category_id is nil
|
31
31
|
When I run "rake db:check_sanity"
|
32
32
|
Then the table "invalid_records" should contain:
|
33
33
|
| User | 1 | {:username=>["is too short (minimum is 3 characters)"]} |
|
34
34
|
| Post | 1 | {:category=>["can't be blank"]} |
|
35
35
|
|
36
|
-
Given the first
|
36
|
+
Given the first author's username is "Greg"
|
37
37
|
When I run "rake db:check_sanity"
|
38
38
|
Then the table "invalid_records" should contain:
|
39
39
|
| Post | 1 | {:category=>["can't be blank"]} |
|
@@ -41,7 +41,7 @@ Feature: Check sanity with db storage
|
|
41
41
|
|
42
42
|
Scenario: Check sanity on database with invalid records that were invalid for different reasons earlier
|
43
43
|
Given the database contains a few valid records
|
44
|
-
And the first
|
44
|
+
And the first author's username is empty and the first post category_id is nil
|
45
45
|
When I run "rake db:check_sanity"
|
46
46
|
Then the table "invalid_records" should contain:
|
47
47
|
| User | 1 | {:username=>["is too short (minimum is 3 characters)"]} |
|
@@ -30,21 +30,21 @@ Given /^I have a rails app using 'active_sanity' with db storage$/ do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
Given /^the database contains a few valid records$/ do
|
33
|
-
|
34
|
-
|
33
|
+
Author.create!(:first_name => "Greg", :last_name => "Bell", :username => "gregbell")
|
34
|
+
Publisher.create!(:first_name => "Sam", :last_name => "Vincent", :username => "samvincent")
|
35
35
|
Category.create!(:name => "Uncategorized")
|
36
|
-
Post.create!(:author =>
|
37
|
-
:title => "How ActiveAdmin changed the world", :body => "
|
36
|
+
Post.create!(:author => Author.first, :category => Category.first,
|
37
|
+
:title => "How ActiveAdmin changed the world", :body => "Lot of love.",
|
38
38
|
:published_at => 4.years.from_now)
|
39
39
|
end
|
40
40
|
|
41
|
-
Given /^the first
|
42
|
-
|
41
|
+
Given /^the first author's username is empty and the first post category_id is nil$/ do
|
42
|
+
Author.first.update_attribute(:username, "")
|
43
43
|
Post.first.update_attribute(:category_id, nil)
|
44
44
|
end
|
45
45
|
|
46
|
-
Given /^the first
|
47
|
-
|
46
|
+
Given /^the first author's username is "([^"]*)"$/ do |username|
|
47
|
+
Author.first.update_attribute('username', username)
|
48
48
|
end
|
49
49
|
|
50
50
|
Given /^the first post category is set$/ do
|
data/features/support/env.rb
CHANGED
@@ -4,17 +4,20 @@ require 'rubygems'
|
|
4
4
|
require "bundler"
|
5
5
|
Bundler.setup
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
raise unless
|
7
|
+
if File.directory?("test/rails_app")
|
8
|
+
Dir.chdir("test/rails_app") do
|
9
|
+
raise unless system("rm -f db/migrate/*create_invalid_records.rb && rake db:drop db:create db:migrate")
|
10
|
+
end
|
11
|
+
end
|
10
12
|
|
11
13
|
After do
|
12
14
|
# Reset DB!
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
tables = ['categories', 'invalid_records', 'posts', 'users']
|
16
|
+
conn = ActiveRecord::Base.connection
|
17
|
+
tables.each do |table|
|
18
|
+
if conn.table_exists?(table)
|
19
|
+
conn.execute("DELETE FROM '#{table}'")
|
20
|
+
conn.execute("DELETE FROM sqlite_sequence WHERE name='#{table}'")
|
21
|
+
end
|
19
22
|
end
|
20
23
|
end
|
@@ -8,30 +8,63 @@ module ActiveSanity
|
|
8
8
|
puts "Sanity Check"
|
9
9
|
puts "Checking the following models: #{models.join(', ')}"
|
10
10
|
|
11
|
+
# TODO: Wouldnt this list already be checked by the next all records call if those records do exist?
|
12
|
+
# This will validate and destroy the records that either dont exist currently, or are now valid. But the ones are continue to be invalid - these will
|
13
|
+
# have been run through the validation process twice
|
11
14
|
check_previously_invalid_records
|
12
15
|
check_all_records
|
13
16
|
end
|
14
17
|
|
18
|
+
# @return [Array] of [ActiveRecord::Base] direct descendants
|
15
19
|
def models
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
@models ||= ActiveRecord::Base.subclasses
|
20
|
+
return @models if @models
|
21
|
+
|
22
|
+
load_all_models
|
23
|
+
|
24
|
+
@models ||= direct_active_record_base_descendants
|
23
25
|
end
|
24
26
|
|
25
27
|
protected
|
26
28
|
|
29
|
+
# Require all files under /app/models.
|
30
|
+
# All models under /lib are required when the rails app loads.
|
31
|
+
def load_all_models
|
32
|
+
Dir["#{Rails.root}/app/models/**/*.rb"].each { |file_path| require file_path rescue nil }
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [Array] of direct ActiveRecord::Base descendants.
|
36
|
+
# Example:
|
37
|
+
# The following tree:
|
38
|
+
# ActiveRecord::Base
|
39
|
+
# |
|
40
|
+
# |- User
|
41
|
+
# |- Account
|
42
|
+
# | |
|
43
|
+
# | |- PersonalAccount
|
44
|
+
# | |- BusinessAccount
|
45
|
+
#
|
46
|
+
# Should return: [Account, User]
|
47
|
+
def direct_active_record_base_descendants
|
48
|
+
ActiveRecord::Base.descendants.select(&:descends_from_active_record?).sort_by(&:name)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Remove records that are now valid from the list of invalid records.
|
27
52
|
def check_previously_invalid_records
|
28
53
|
return unless InvalidRecord.table_exists?
|
29
54
|
|
30
55
|
InvalidRecord.find_each do |invalid_record|
|
31
|
-
|
56
|
+
begin
|
57
|
+
invalid_record.destroy if invalid_record.record.valid?
|
58
|
+
rescue
|
59
|
+
# Record does not exists.
|
60
|
+
invalid_record.delete
|
61
|
+
end
|
32
62
|
end
|
33
63
|
end
|
34
64
|
|
65
|
+
# Go over every single record. When the record is not valid
|
66
|
+
# log it to STDOUT and into the invalid_records table if it exists.
|
67
|
+
#
|
35
68
|
def check_all_records
|
36
69
|
models.each do |model|
|
37
70
|
begin
|
@@ -54,22 +87,30 @@ module ActiveSanity
|
|
54
87
|
store_invalid_record(record)
|
55
88
|
end
|
56
89
|
|
90
|
+
# Say that the record is invalid. Example:
|
91
|
+
#
|
92
|
+
# Account | 10 | :name => "Can't be blank"
|
57
93
|
def log_invalid_record(record)
|
58
|
-
puts record
|
94
|
+
puts "#{type_of(record)} | #{record.id} | #{pretty_errors(record)}"
|
59
95
|
end
|
60
|
-
|
96
|
+
|
97
|
+
# Store invalid record in InvalidRecord table if it exists
|
61
98
|
def store_invalid_record(record)
|
62
99
|
return unless InvalidRecord.table_exists?
|
63
100
|
|
64
|
-
invalid_record = InvalidRecord.where(:record_type => record
|
101
|
+
invalid_record = InvalidRecord.where(:record_type => type_of(record), :record_id => record.id).first
|
65
102
|
invalid_record ||= InvalidRecord.new
|
66
103
|
invalid_record.record = record
|
67
104
|
invalid_record.validation_errors = record.errors
|
68
105
|
invalid_record.save!
|
69
106
|
end
|
70
107
|
|
108
|
+
def type_of(record)
|
109
|
+
record.class.base_class
|
110
|
+
end
|
111
|
+
|
71
112
|
def pretty_errors(record)
|
72
|
-
record.errors.inspect.sub(/^#<OrderedHash
|
113
|
+
record.errors.inspect.sub(/^#<OrderedHash (.*)>$/, '\1')
|
73
114
|
end
|
74
115
|
end
|
75
116
|
end
|
data/test/rails_template.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
|
2
2
|
# Generate some test models
|
3
|
+
|
4
|
+
# Post
|
3
5
|
generate :model, "post title:string body:text published_at:datetime author_id:integer category_id:integer"
|
4
6
|
post_code = <<-CODE
|
5
7
|
belongs_to :author, :class_name => 'User'
|
@@ -10,7 +12,17 @@ post_code = <<-CODE
|
|
10
12
|
CODE
|
11
13
|
inject_into_file 'app/models/post.rb', post_code, :after => "class Post < ActiveRecord::Base\n"
|
12
14
|
|
13
|
-
|
15
|
+
# Category
|
16
|
+
generate :model, 'category name:string description:text'
|
17
|
+
category_code = <<-CODE
|
18
|
+
has_many :posts
|
19
|
+
|
20
|
+
validates_presence_of :name
|
21
|
+
CODE
|
22
|
+
inject_into_file 'app/models/category.rb', category_code, :after => "class Category < ActiveRecord::Base\n"
|
23
|
+
|
24
|
+
# User
|
25
|
+
generate :model, "user first_name:string last_name:string username:string type:string"
|
14
26
|
user_code = <<-CODE
|
15
27
|
has_many :posts, :foreign_key => 'author_id'
|
16
28
|
|
@@ -19,14 +31,13 @@ user_code = <<-CODE
|
|
19
31
|
CODE
|
20
32
|
inject_into_file 'app/models/user.rb', user_code, :after => "class User < ActiveRecord::Base\n"
|
21
33
|
|
22
|
-
|
23
|
-
|
24
|
-
|
34
|
+
# Author < User
|
35
|
+
create_file 'app/models/author.rb', "class Author < User; end"
|
36
|
+
# Publisher < User
|
37
|
+
create_file 'app/models/publisher.rb', "class Publisher < User; end"
|
25
38
|
|
26
|
-
validates_presence_of :name
|
27
|
-
CODE
|
28
|
-
inject_into_file 'app/models/category.rb', category_code, :after => "class Category < ActiveRecord::Base\n"
|
29
39
|
|
40
|
+
# NotAModel
|
30
41
|
create_file 'app/models/not_a_model.rb', "class NotAModel; end"
|
31
42
|
|
32
43
|
# Add active_sanity
|
@@ -34,4 +45,3 @@ append_file 'Gemfile', "gem 'active_sanity', :path => '../../'"
|
|
34
45
|
|
35
46
|
run "bundle"
|
36
47
|
rake "db:migrate"
|
37
|
-
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_sanity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- VersaPay
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2011-
|
19
|
+
date: 2011-09-06 00:00:00 -07:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|