table_warnings 0.0.2

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/.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