table_warnings 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ rdoc/*
5
+ data_miner.log
6
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in table_warnings.gemspec
4
+ gemspec
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,11 @@
1
+ require 'singleton'
2
+ require 'set'
3
+ module TableWarnings
4
+ class Config
5
+ include ::Singleton
6
+
7
+ def warnings
8
+ @warnings ||= ::Hash.new { |hash, key| hash[key] = ::Set.new }
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module TableWarnings
2
+ VERSION = "0.0.2"
3
+ 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