table_warnings 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/Gemfile +4 -0
- data/README.rdoc +26 -0
- data/Rakefile +22 -0
- data/lib/table_warnings/config.rb +11 -0
- data/lib/table_warnings/version.rb +3 -0
- data/lib/table_warnings/warning/blank.rb +23 -0
- data/lib/table_warnings/warning/size.rb +34 -0
- data/lib/table_warnings/warning.rb +29 -0
- data/lib/table_warnings.rb +44 -0
- data/table_warnings.gemspec +24 -0
- data/test/helper.rb +20 -0
- data/test/test_table_warnings.rb +33 -0
- metadata +124 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
=table_warnings
|
2
|
+
|
3
|
+
NOTE: only for activerecord right now because it uses <tt>count(:conditions => [...])</tt>
|
4
|
+
|
5
|
+
==How to define warning signs
|
6
|
+
|
7
|
+
class AutomobileMake < ActiveRecord::Base
|
8
|
+
warn_if_blanks_in :name
|
9
|
+
warn_if_blanks_in :fuel_efficiency
|
10
|
+
warn_unless_size_is :hundreds
|
11
|
+
end
|
12
|
+
|
13
|
+
==How to see warnings for the table
|
14
|
+
|
15
|
+
?> AutomobileMake.table_warnings
|
16
|
+
=> [ "Table is not of expected size" ]
|
17
|
+
|
18
|
+
==Defense
|
19
|
+
|
20
|
+
* This is not the same as validations, because those interfere with the saving of individual records
|
21
|
+
|
22
|
+
==Self-criticism
|
23
|
+
|
24
|
+
* Maybe this should work work on any class that defines <tt>.all</tt>
|
25
|
+
|
26
|
+
Copyright 2011 Seamus Abshere
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rake'
|
5
|
+
require 'rake/testtask'
|
6
|
+
Rake::TestTask.new(:test) do |test|
|
7
|
+
test.libs << 'lib' << 'test'
|
8
|
+
test.pattern = 'test/**/test_*.rb'
|
9
|
+
test.verbose = true
|
10
|
+
end
|
11
|
+
|
12
|
+
task :default => :test
|
13
|
+
|
14
|
+
require 'rake/rdoctask'
|
15
|
+
Rake::RDocTask.new do |rdoc|
|
16
|
+
version = TableWarnings::VERSION
|
17
|
+
|
18
|
+
rdoc.rdoc_dir = 'rdoc'
|
19
|
+
rdoc.title = "table_warnings #{version}"
|
20
|
+
rdoc.rdoc_files.include('README*')
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module TableWarnings
|
2
|
+
class Warning
|
3
|
+
class Blank < Warning
|
4
|
+
attr_reader :column_name
|
5
|
+
|
6
|
+
def effective_column_names
|
7
|
+
if column_name
|
8
|
+
[column_name]
|
9
|
+
else
|
10
|
+
table.column_names
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def messages
|
15
|
+
effective_column_names.map do |c|
|
16
|
+
if table.count(:conditions => { c => ''}) > 0 or table.count(:conditions => { c => nil }) > 0
|
17
|
+
"There are blanks in the `#{c}` column."
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module TableWarnings
|
2
|
+
class Warning
|
3
|
+
class Size < Warning
|
4
|
+
attr_reader :approximate_size
|
5
|
+
|
6
|
+
def allowed_range
|
7
|
+
case approximate_size
|
8
|
+
when :few
|
9
|
+
1..10
|
10
|
+
when :dozens, :tens
|
11
|
+
10..100
|
12
|
+
when :hundreds
|
13
|
+
100..1_000
|
14
|
+
when :thousands
|
15
|
+
1_000..99_000
|
16
|
+
when :hundreds_of_thousands
|
17
|
+
100_000..1_000_000
|
18
|
+
when :millions
|
19
|
+
1_000_000..1_000_000_000
|
20
|
+
when Range
|
21
|
+
approximate_size
|
22
|
+
when Numeric
|
23
|
+
approximate_size..approximate_size
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def messages
|
28
|
+
unless allowed_range.include? table.count
|
29
|
+
"Table is not of expected size (expected: #{allowed_range.to_s}, actual: #{table.count})"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module TableWarnings
|
2
|
+
class Warning
|
3
|
+
autoload :Blank, 'table_warnings/warning/blank'
|
4
|
+
autoload :Size, 'table_warnings/warning/size'
|
5
|
+
|
6
|
+
attr_reader :table
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
options.each do |k, v|
|
10
|
+
instance_variable_set "@#{k}", v
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_hash
|
15
|
+
instance_variables.sort.inject({}) do |memo, ivar_name|
|
16
|
+
memo[ivar_name.to_s.sub('@', '')] = instance_variable_get ivar_name
|
17
|
+
memo
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def hash
|
22
|
+
to_hash.hash
|
23
|
+
end
|
24
|
+
|
25
|
+
def eql?(other)
|
26
|
+
other.is_a?(Warning) and self.to_hash == other.to_hash
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module TableWarnings
|
4
|
+
autoload :Config, 'table_warnings/config'
|
5
|
+
autoload :Warning, 'table_warnings/warning'
|
6
|
+
|
7
|
+
def self.config #:nodoc: all
|
8
|
+
Config.instance
|
9
|
+
end
|
10
|
+
|
11
|
+
# Get current warnings on the table.
|
12
|
+
def table_warnings
|
13
|
+
::TableWarnings.config.warnings[self].map { |w| w.messages }.flatten.compact.sort
|
14
|
+
end
|
15
|
+
|
16
|
+
# Warn if there are blanks in a certain column.
|
17
|
+
#
|
18
|
+
# Blank includes both NULL and "" (empty string)
|
19
|
+
def warn_if_blanks_in(column_name)
|
20
|
+
warning = ::TableWarnings::Warning::Blank.new :table => self, :column_name => column_name
|
21
|
+
::TableWarnings.config.warnings[self].add warning
|
22
|
+
end
|
23
|
+
|
24
|
+
# Warn if there are blanks in ANY column.
|
25
|
+
#
|
26
|
+
# Blank includes both NULL and "" (empty string)
|
27
|
+
def warn_if_any_blanks
|
28
|
+
warning = ::TableWarnings::Warning::Blank.new :table => self
|
29
|
+
::TableWarnings.config.warnings[self].add warning
|
30
|
+
end
|
31
|
+
|
32
|
+
# Warn if the number of records falls out of an (approximate) range.
|
33
|
+
#
|
34
|
+
# Approximations: :few, :tens, :dozens, :hundreds, :thousands, :hundreds_of_thousands, :millions
|
35
|
+
# Exact: pass a Range or a Numeric
|
36
|
+
def warn_unless_size_is(approximate_size)
|
37
|
+
warning = ::TableWarnings::Warning::Size.new :table => self, :approximate_size => approximate_size
|
38
|
+
::TableWarnings.config.warnings[self].add warning
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
unless ::ActiveRecord::Base.method_defined? :table_warnings
|
43
|
+
::ActiveRecord::Base.extend ::TableWarnings
|
44
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'table_warnings/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'table_warnings'
|
7
|
+
s.version = TableWarnings::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ['Seamus Abshere']
|
10
|
+
s.email = ['seamus@abshere.net']
|
11
|
+
s.homepage = 'https://github.com/seamusabshere/table_warnings'
|
12
|
+
s.summary = %q{It's called validations to remind people of per-record validations, but it works on the table, and is meant to be used after a table is completely populated.}
|
13
|
+
s.description = %q{Validate an entire [ActiveRecord] table, checking for things like blank rows or total number of rows}
|
14
|
+
|
15
|
+
s.rubyforge_project = 'table_warnings'
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ['lib']
|
21
|
+
s.add_development_dependency 'fastercsv'
|
22
|
+
s.add_development_dependency 'earth', '0.3.11'
|
23
|
+
s.add_dependency 'activerecord' # for now
|
24
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.setup
|
4
|
+
require 'test/unit'
|
5
|
+
require 'active_support/all'
|
6
|
+
require 'active_record'
|
7
|
+
# thanks authlogic!
|
8
|
+
ActiveRecord::Schema.verbose = false
|
9
|
+
begin
|
10
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
11
|
+
rescue ArgumentError
|
12
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:")
|
13
|
+
end
|
14
|
+
require 'earth'
|
15
|
+
Earth.init :automobile, :apply_schemas => true
|
16
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
17
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
18
|
+
require 'table_warnings'
|
19
|
+
class Test::Unit::TestCase
|
20
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class AutomobileMake < ActiveRecord::Base
|
4
|
+
warn_if_blanks_in :name
|
5
|
+
warn_if_blanks_in :fuel_efficiency
|
6
|
+
warn_unless_size_is :hundreds
|
7
|
+
warn_unless_size_is 100..1000
|
8
|
+
end
|
9
|
+
|
10
|
+
class AutomobileFuelType < ActiveRecord::Base
|
11
|
+
warn_if_any_blanks
|
12
|
+
warn_unless_size_is :few
|
13
|
+
warn_unless_size_is 1..6
|
14
|
+
end
|
15
|
+
|
16
|
+
AutomobileMake.create! :name => '', :fuel_efficiency => nil, :fuel_efficiency_units => 'kilometres_per_litre'
|
17
|
+
AutomobileMake.create! :name => 'Alfa Romeo', :fuel_efficiency => 10.4075, :fuel_efficiency_units => 'kilometres_per_litre'
|
18
|
+
|
19
|
+
AutomobileFuelType.create! :name => 'gas'
|
20
|
+
AutomobileFuelType.create! :name => 'diesel'
|
21
|
+
|
22
|
+
class TestTableWarnings < Test::Unit::TestCase
|
23
|
+
def test_warn_for_blanks_in_specific_columns
|
24
|
+
assert AutomobileMake.table_warnings.one? { |w| w =~ /blanks in.*name.*column/ }
|
25
|
+
assert AutomobileMake.table_warnings.one? { |w| w =~ /blanks in.*fuel_efficiency.*column/ }
|
26
|
+
end
|
27
|
+
def test_warn_of_size
|
28
|
+
assert AutomobileMake.table_warnings.many? { |w| w =~ /expected.*size/ }
|
29
|
+
end
|
30
|
+
def test_warn_for_blanks_in_any_column
|
31
|
+
assert AutomobileFuelType.table_warnings.one? { |w| w =~ /blanks in.*code.*column/ }
|
32
|
+
end
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: table_warnings
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Seamus Abshere
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-02-18 00:00:00 -06:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: fastercsv
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: earth
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - "="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 5
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
- 3
|
47
|
+
- 11
|
48
|
+
version: 0.3.11
|
49
|
+
type: :development
|
50
|
+
version_requirements: *id002
|
51
|
+
- !ruby/object:Gem::Dependency
|
52
|
+
name: activerecord
|
53
|
+
prerelease: false
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 3
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
type: :runtime
|
64
|
+
version_requirements: *id003
|
65
|
+
description: Validate an entire [ActiveRecord] table, checking for things like blank rows or total number of rows
|
66
|
+
email:
|
67
|
+
- seamus@abshere.net
|
68
|
+
executables: []
|
69
|
+
|
70
|
+
extensions: []
|
71
|
+
|
72
|
+
extra_rdoc_files: []
|
73
|
+
|
74
|
+
files:
|
75
|
+
- .gitignore
|
76
|
+
- Gemfile
|
77
|
+
- README.rdoc
|
78
|
+
- Rakefile
|
79
|
+
- lib/table_warnings.rb
|
80
|
+
- lib/table_warnings/config.rb
|
81
|
+
- lib/table_warnings/version.rb
|
82
|
+
- lib/table_warnings/warning.rb
|
83
|
+
- lib/table_warnings/warning/blank.rb
|
84
|
+
- lib/table_warnings/warning/size.rb
|
85
|
+
- table_warnings.gemspec
|
86
|
+
- test/helper.rb
|
87
|
+
- test/test_table_warnings.rb
|
88
|
+
has_rdoc: true
|
89
|
+
homepage: https://github.com/seamusabshere/table_warnings
|
90
|
+
licenses: []
|
91
|
+
|
92
|
+
post_install_message:
|
93
|
+
rdoc_options: []
|
94
|
+
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
hash: 3
|
103
|
+
segments:
|
104
|
+
- 0
|
105
|
+
version: "0"
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
hash: 3
|
112
|
+
segments:
|
113
|
+
- 0
|
114
|
+
version: "0"
|
115
|
+
requirements: []
|
116
|
+
|
117
|
+
rubyforge_project: table_warnings
|
118
|
+
rubygems_version: 1.3.7
|
119
|
+
signing_key:
|
120
|
+
specification_version: 3
|
121
|
+
summary: It's called validations to remind people of per-record validations, but it works on the table, and is meant to be used after a table is completely populated.
|
122
|
+
test_files:
|
123
|
+
- test/helper.rb
|
124
|
+
- test/test_table_warnings.rb
|