cwninja-active_record_lint 0.0.3

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/README.markdown ADDED
@@ -0,0 +1,23 @@
1
+ ActiveRecord::Lint
2
+ ================
3
+
4
+ A library to support the automatic checking for the doing of stupid things
5
+ with ActiveRecord.
6
+
7
+ AR::Lint is not big, nor is it clever, nor is it that well written.
8
+ It makes recommendations based upon what I have found to be good practice, with
9
+ only anecdotal evidence to support it.
10
+
11
+ This is *not* a substitute for a DB admin, nor is it a substitute for knoledge.
12
+
13
+ Your mileage may vary, remember to check your tire pressure.
14
+
15
+ Usage
16
+ -----
17
+
18
+ You can check a typical rails application by executing:
19
+ > $ arlint path/to/rails/app
20
+
21
+ Support for automated tests and making it work with rake is something I could do to get around to.
22
+
23
+ Copyright (c) 2008 Tom Lea, released under the MIT Licence
data/Rakefile ADDED
@@ -0,0 +1,64 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+ require 'rake/gempackagetask'
6
+ require 'date'
7
+
8
+ desc 'Default: run unit tests.'
9
+ task :default => :test
10
+
11
+ namespace :test do
12
+ desc 'Functional tests.'
13
+ Rake::TestTask.new(:functional) do |t|
14
+ t.libs << 'lib'
15
+ t.pattern = 'test/functional/*_test.rb'
16
+ t.verbose = true
17
+ end
18
+ desc 'Unit tests.'
19
+ Rake::TestTask.new(:unit) do |t|
20
+ t.libs << 'lib'
21
+ t.pattern = 'test/unit/*_test.rb'
22
+ t.verbose = true
23
+ end
24
+ end
25
+
26
+ task :test => ["test:functional", "test:unit"]
27
+
28
+ spec = Gem::Specification.new do |s|
29
+ s.name = %q{active_record_lint}
30
+ s.version = "0.0.3"
31
+ s.summary = %q{Rails tool to find foreign keys without indexes and other common issues.}
32
+ s.description = %q{A library to support the automatic checking for the doing of stupid things with ActiveRecord.}
33
+
34
+ s.executables = ["arlint"]
35
+ s.files = FileList['[A-Z]*', 'lib/**/*.rb', 'test/**/*.rb']
36
+ s.require_path = 'lib'
37
+ s.test_files = Dir[*['test/**/*_test.rb']]
38
+ s.homepage = "http://github.com/cwninja/active_record_lint"
39
+
40
+ s.has_rdoc = true
41
+ s.extra_rdoc_files = ["README.markdown"]
42
+ s.rdoc_options = ['--line-numbers', '--inline-source', "--main", "README.markdown"]
43
+
44
+ s.authors = ["Tom Lea"]
45
+ s.email = %q{commits@tomlea.co.uk}
46
+
47
+ s.platform = Gem::Platform::RUBY
48
+ end
49
+
50
+ Rake::GemPackageTask.new spec do |pkg|
51
+ pkg.need_tar = true
52
+ pkg.need_zip = true
53
+ end
54
+
55
+ desc "Clean files generated by rake tasks"
56
+ task :clobber => [:clobber_rdoc, :clobber_package]
57
+
58
+ desc "Generate a gemspec file"
59
+ task :gemspec do
60
+ File.open("#{spec.name}.gemspec", 'w') do |f|
61
+ f.write spec.to_ruby
62
+ end
63
+ end
64
+
data/bin/arlint ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ path = ARGV.last || Dir.pwd
4
+
5
+ boot_path = File.join(path, 'config', 'boot.rb')
6
+ environment_path = File.join(path, 'config', 'environment.rb')
7
+
8
+ unless(File.exists?(boot_path) and File.exists?(environment_path))
9
+ puts "Usage: #{$0} path/to/rails/root"
10
+ exit(1)
11
+ end
12
+
13
+ require boot_path
14
+ require environment_path
15
+ require 'active_record_lint'
16
+
17
+ ActiveRecord::Lint.load_models(path)
18
+
19
+ scanner = ActiveRecord::Lint::Scanner.new()
20
+ reporter = ActiveRecord::Lint::Reporter.new(scanner)
21
+
22
+ puts reporter
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ require 'active_record'
3
+
4
+ module ActiveRecord::Lint
5
+ def load_models(rails_root)
6
+ pattern = File.join(rails_root, "app", "models", "*.rb")
7
+ Dir.glob(pattern){|file|
8
+ load( file )
9
+ }
10
+ end
11
+
12
+ def unload_models
13
+ models = ActiveRecord::Base.send :class_variable_get, :@@subclasses
14
+ models = models.keys - [ActiveRecord::Base]
15
+ models.map(&:name).each do |name|
16
+ Object.send :remove_const, name unless name.nil? or name.empty?
17
+ end
18
+ ActiveRecord::Base.send :class_variable_set, :@@subclasses, {}
19
+ end
20
+
21
+ def missing_indexes(options = {})
22
+ load_models(options[:rails_root] || RAILS_ROOT)
23
+ Scanner.new(options[:connection] || ActiveRecord::Base.connection).missing_indexes
24
+ end
25
+
26
+ extend self
27
+ end
28
+
29
+
30
+ Dir.glob(File.join(File.dirname(__FILE__), "lint", "*.rb")) do |file|
31
+ require file
32
+ end
@@ -0,0 +1,28 @@
1
+ unless defined? Memoize
2
+ module Memoize
3
+
4
+ def self.included(other)
5
+ other.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ def memoize(*methods)
10
+ methods.each do |method|
11
+ define_method "#{method}_with_memoize" do |*args|
12
+ memoize_store_for(method)[args] ||= send("#{method}_without_memoize", *args)
13
+ end
14
+
15
+ alias_method_chain method, :memoize
16
+ end
17
+ end
18
+ end
19
+
20
+ def memoize_store_for(method)
21
+ unless store = instance_variable_get("@_#{method}_memoized")
22
+ instance_variable_set("@_#{method}_memoized", store = {})
23
+ end
24
+ store
25
+ end
26
+ end
27
+
28
+ end
@@ -0,0 +1,53 @@
1
+ module ActiveRecord::Lint
2
+ class Pair
3
+ include Comparable
4
+ attr_accessor :a, :b
5
+
6
+ def initialize(a, b)
7
+ @a,@b=a,b
8
+ end
9
+
10
+ def <=>(other)
11
+ (a <=> other.a).zero? ? (b <=> other.b) : (a <=> other.a)
12
+ end
13
+
14
+ def eql?(other)
15
+ (self <=> other) == 0
16
+ end
17
+
18
+ def pair_name
19
+ @pair_name ||= self.class.name.split("::").last
20
+ end
21
+
22
+ def inspect
23
+ "#{pair_name}[#{a.inspect}, #{b.inspect}]"
24
+ end
25
+
26
+ def hash
27
+ a.hash ^ b.hash
28
+ end
29
+
30
+ def to_ary
31
+ [a,b]
32
+ end
33
+
34
+ alias to_a to_ary
35
+
36
+ class << self
37
+ alias [] new
38
+ end
39
+ end
40
+
41
+ class TableColumnPair < Pair
42
+ alias table a
43
+ alias column b
44
+ end
45
+
46
+ class TableKeyPair < TableColumnPair
47
+ alias key b
48
+ end
49
+
50
+ class TableIndexPair < TableColumnPair
51
+ alias index b
52
+ end
53
+ end
@@ -0,0 +1,89 @@
1
+ require File.join(File.dirname(__FILE__), "pairs")
2
+
3
+ module ActiveRecord::Lint
4
+ class MissingIndex < TableIndexPair
5
+ def to_s
6
+ "The foreign key '#{index}' is not indexed on '#{table}'."
7
+ end
8
+ end
9
+
10
+ class MissingTable
11
+ include Comparable
12
+ attr_reader :table
13
+
14
+ def initialize(table)
15
+ @table=table
16
+ end
17
+
18
+ def <=> (other)
19
+ table <=> other.table
20
+ end
21
+
22
+ def to_s
23
+ "Expected the table '#{table}' to exist."
24
+ end
25
+ end
26
+
27
+ class MissingForeignKey < TableKeyPair
28
+ def to_s
29
+ "Missing foreign key '#{key}' on '#{table}'."
30
+ end
31
+ end
32
+
33
+
34
+ class Reporter
35
+ include Memoize
36
+ SUMMARY_NAMES = ["missing_indexes", "missing_tables", "missing_foreign_keys"]
37
+
38
+ def initialize(scanner)
39
+ @scanner = scanner
40
+ end
41
+
42
+ def missing_indexes
43
+ @scanner.missing_indexes.map{|pair| MissingIndex[*pair.to_ary] }
44
+ end
45
+ memoize :missing_indexes
46
+
47
+ def missing_tables
48
+ tables = @scanner.missing_tables.map{|table_issue| MissingTable.new(table_issue) }
49
+ if defined?(ActionController::Base) and ActionController::Base.session_store != :active_record_store
50
+ tables.reject!{|table| table.table}
51
+ end
52
+ tables
53
+ end
54
+ memoize :missing_tables
55
+
56
+ def missing_foreign_keys
57
+ @scanner.missing_foreign_keys.map{|pair| MissingForeignKey[*pair.to_ary] }
58
+ end
59
+ memoize :missing_foreign_keys
60
+
61
+ def issues
62
+ SUMMARY_NAMES.map{|name| send(name) }.sum
63
+ end
64
+
65
+
66
+ def to_s
67
+ lines = returning([]){|output|
68
+ SUMMARY_NAMES.each do |name|
69
+ issues = send(name)
70
+ unless issues.empty?
71
+ output << "== #{name} =="
72
+ issues.each do |issue|
73
+ output << "* #{issue}"
74
+ end
75
+ end
76
+ end
77
+ }
78
+ if lines.empty?
79
+ "No issues found"
80
+ else
81
+ lines.join("\n")
82
+ end
83
+ end
84
+
85
+ private
86
+ attr_writer *SUMMARY_NAMES
87
+ end
88
+ end
89
+
@@ -0,0 +1,61 @@
1
+ class ActiveRecord::Lint::Scanner
2
+ include ActiveRecord::Lint
3
+ include Memoize
4
+
5
+ def initialize(connection = nil)
6
+ @connection = connection || ActiveRecord::Base.connection
7
+ end
8
+
9
+ def missing_indexes
10
+ foreign_keys - indexes
11
+ end
12
+
13
+ def missing_tables
14
+ classes.map{|klass| klass.table_name } - @connection.tables
15
+ end
16
+
17
+ def missing_foreign_keys
18
+ foreign_keys - columns
19
+ end
20
+
21
+ def foreign_keys
22
+ returning [] do |foreign_keys|
23
+ classes.each do |klass|
24
+ table_name = klass.table_name
25
+ klass.reflect_on_all_associations(:belongs_to).map(&:primary_key_name).each do |foreign_key|
26
+ foreign_keys << TableColumnPair.new(table_name, foreign_key)
27
+ end
28
+ end
29
+ end.uniq
30
+ end
31
+ memoize :foreign_keys
32
+
33
+ def columns
34
+ returning [] do |columns|
35
+ @connection.tables.each do |table|
36
+ @connection.columns(table).each do |column|
37
+ columns << TableColumnPair.new(table, column.name)
38
+ end
39
+ end
40
+ end.uniq
41
+ end
42
+ memoize :columns
43
+
44
+ def indexes
45
+ returning [] do |indexes|
46
+ @connection.tables.each do |table|
47
+ column_sets = @connection.indexes(table).map(&:columns)
48
+ column_sets.select{|col| col.size == 1}.flatten.each do |index|
49
+ indexes << TableIndexPair.new(table, index)
50
+ end
51
+ end
52
+ end.uniq
53
+ end
54
+ memoize :indexes
55
+
56
+ def classes
57
+ ActiveRecord::Base.send(:subclasses)
58
+ end
59
+ memoize :classes
60
+
61
+ end
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), "active_record", "lint")
@@ -0,0 +1,5 @@
1
+ class Crime < ActiveRecord::Base
2
+ has_many :incidents
3
+ has_many :victims, :through => :incidents
4
+ has_many :criminals, :through => :incidents
5
+ end
@@ -0,0 +1,5 @@
1
+ class Criminal < ActiveRecord::Base
2
+ has_many :incidents
3
+ has_many :victims, :through => :incidents
4
+ has_many :crimes, :through => :incidents
5
+ end
@@ -0,0 +1,5 @@
1
+ class Incident < ActiveRecord::Base
2
+ belongs_to :criminal
3
+ belongs_to :victim
4
+ belongs_to :crime
5
+ end
@@ -0,0 +1,3 @@
1
+ class Victim < ActiveRecord::Base
2
+ has_many :incidents
3
+ end
@@ -0,0 +1,26 @@
1
+ require File.join(File.dirname(__FILE__), "..", "test_helper")
2
+
3
+ class MissingForeignKeysFunctionalTest < Test::Unit::TestCase
4
+ include CriminalDatabase
5
+ include ActiveRecord::Lint
6
+
7
+ def setup
8
+ @rails_root = File.join(File.dirname(__FILE__), "..", "fixtures", "criminals")
9
+ ActiveRecord::Lint::load_models(@rails_root)
10
+ super
11
+ @connection.remove_column :incidents, :criminal_id
12
+ end
13
+
14
+ def test_should_not_error_because_we_are_missing_criminal_id
15
+ missing_indexes = ActiveRecord::Lint::Scanner.new(@connection).missing_indexes
16
+
17
+ assert_array_equal [Pair["incidents", "criminal_id"], Pair["incidents", "crime_id"]], missing_indexes
18
+ end
19
+
20
+ def test_should_report_lack_of_criminal_id_on_incidents_table
21
+ missing_foreign_keys = ActiveRecord::Lint::Scanner.new(@connection).missing_foreign_keys
22
+
23
+ assert_array_equal [Pair["incidents", "criminal_id"]], missing_foreign_keys
24
+ end
25
+
26
+ end
@@ -0,0 +1,35 @@
1
+ require File.join(File.dirname(__FILE__), "..", "test_helper")
2
+
3
+ class MissingIndexesAssociationsFunctionalTest < Test::Unit::TestCase
4
+ include CriminalDatabase
5
+ Pair = ActiveRecord::Lint::Pair
6
+ def setup
7
+ ActiveRecord::Lint::unload_models
8
+ @rails_root = File.join(File.dirname(__FILE__), "..", "fixtures", "criminals")
9
+ super
10
+ end
11
+
12
+ def test_should_know_we_need_an_index_on_victims
13
+ ActiveRecord::Lint::load_models(@rails_root)
14
+
15
+ missing_indexes = ActiveRecord::Lint::Scanner.new(@connection).missing_indexes
16
+
17
+ assert_array_equal [Pair["incidents", "criminal_id"], Pair["incidents", "crime_id"]], missing_indexes
18
+ end
19
+
20
+ def test_should_be_able_to_call_missing_indexes_on_module
21
+ missing_indexes = ActiveRecord::Lint.missing_indexes(:rails_root => @rails_root)
22
+
23
+ assert_array_equal [Pair["incidents", "criminal_id"], Pair["incidents", "crime_id"]], missing_indexes
24
+ end
25
+
26
+ def test_should_handle_inherited_models
27
+ ActiveRecord::Lint::load_models(@rails_root)
28
+
29
+ my_model = Class.new(Incident)
30
+ missing_indexes = ActiveRecord::Lint::Scanner.new(@connection).missing_indexes
31
+
32
+ assert_array_equal [Pair["incidents", "criminal_id"], Pair["incidents", "crime_id"]], missing_indexes
33
+ end
34
+
35
+ end
@@ -0,0 +1,26 @@
1
+ require File.join(File.dirname(__FILE__), "..", "test_helper")
2
+
3
+ class MissingTablesFunctionalTest < Test::Unit::TestCase
4
+ include CriminalDatabase
5
+ Pair = ActiveRecord::Lint::Pair
6
+
7
+ def setup
8
+ @rails_root = File.join(File.dirname(__FILE__), "..", "fixtures", "criminals")
9
+ ActiveRecord::Lint::load_models(@rails_root)
10
+ super
11
+ @connection.drop_table :criminals
12
+ end
13
+
14
+ def test_should_not_error_because_we_have_no_criminals_table
15
+ missing_indexes = ActiveRecord::Lint::Scanner.new(@connection).missing_indexes
16
+
17
+ assert_array_equal [Pair["incidents", "criminal_id"], Pair["incidents", "crime_id"]], missing_indexes
18
+ end
19
+
20
+ def test_should_report_lack_of_criminals_table
21
+ missing_tables = ActiveRecord::Lint::Scanner.new(@connection).missing_tables
22
+
23
+ assert_array_equal ["criminals"], missing_tables
24
+ end
25
+
26
+ end
@@ -0,0 +1,85 @@
1
+ require File.join(File.dirname(__FILE__), "..", "test_helper")
2
+
3
+ class ReporterMissingIndexesFunctionalTest < Test::Unit::TestCase
4
+ include CriminalDatabase
5
+ Lint = ActiveRecord::Lint
6
+ Pair = Lint::Pair
7
+
8
+ def setup
9
+ super
10
+ @rails_root = File.join(File.dirname(__FILE__), "..", "fixtures", "criminals")
11
+ Lint::load_models(@rails_root)
12
+ end
13
+
14
+ def test_should_report_missing_indexes_on_incidents
15
+ scanner = Lint::Scanner.new(@connection)
16
+ reporter = Lint::Reporter.new(scanner)
17
+
18
+ assert_array_includes Lint::MissingIndex["incidents", "crime_id"], Lint::MissingIndex["incidents", "criminal_id"], reporter.missing_indexes
19
+ end
20
+
21
+ def test_issues_should_report_missing_indexes_on_incidents
22
+ scanner = Lint::Scanner.new(@connection)
23
+ reporter = Lint::Reporter.new(scanner)
24
+
25
+ assert_array_includes Lint::MissingIndex["incidents", "crime_id"], Lint::MissingIndex["incidents", "criminal_id"], reporter.issues
26
+ end
27
+
28
+ end
29
+
30
+
31
+ class ReporterMissingTablesFunctionalTest < Test::Unit::TestCase
32
+ include CriminalDatabase
33
+ Lint = ActiveRecord::Lint
34
+ Pair = Lint::Pair
35
+
36
+ def setup
37
+ super
38
+ @connection.drop_table :criminals
39
+ @rails_root = File.join(File.dirname(__FILE__), "..", "fixtures", "criminals")
40
+ Lint::load_models(@rails_root)
41
+ end
42
+
43
+ def test_should_report_missing_table_criminals
44
+ scanner = Lint::Scanner.new(@connection)
45
+ reporter = Lint::Reporter.new(scanner)
46
+
47
+ assert_array_includes Lint::MissingTable.new("criminals"), reporter.missing_tables
48
+ end
49
+
50
+ def test_issues_should_report_missing_table_criminals
51
+ scanner = Lint::Scanner.new(@connection)
52
+ reporter = Lint::Reporter.new(scanner)
53
+
54
+ assert_array_includes Lint::MissingTable.new("criminals"), reporter.issues
55
+ end
56
+
57
+ end
58
+
59
+ class ReporterMissingForeignKeysFunctionalTest < Test::Unit::TestCase
60
+ include CriminalDatabase
61
+ Lint = ActiveRecord::Lint
62
+ Pair = Lint::Pair
63
+
64
+ def setup
65
+ super
66
+ @connection.remove_column :incidents, :criminal_id
67
+ @rails_root = File.join(File.dirname(__FILE__), "..", "fixtures", "criminals")
68
+ Lint::load_models(@rails_root)
69
+ end
70
+
71
+ def test_should_report_missing_table_criminals
72
+ scanner = Lint::Scanner.new(@connection)
73
+ reporter = Lint::Reporter.new(scanner)
74
+
75
+ assert_array_includes Lint::MissingForeignKey["incidents", "criminal_id"], reporter.missing_foreign_keys
76
+ end
77
+
78
+ def test_issues_should_report_missing_table_criminals
79
+ scanner = Lint::Scanner.new(@connection)
80
+ reporter = Lint::Reporter.new(scanner)
81
+
82
+ assert_array_includes Lint::MissingForeignKey["incidents", "criminal_id"], reporter.issues
83
+ end
84
+
85
+ end
@@ -0,0 +1,87 @@
1
+ require 'test/unit'
2
+
3
+ require File.join(File.dirname(__FILE__), "..", "lib", "active_record_lint")
4
+
5
+ module CriminalDatabase
6
+ def self.included(other)
7
+ other.with_temp_db do
8
+ create_table :crimes do |t|
9
+ end
10
+
11
+ create_table :criminals do |t|
12
+ end
13
+
14
+ create_table :incidents do |t|
15
+ t.references :criminal
16
+ t.references :victim
17
+ t.references :crime
18
+ end
19
+
20
+ add_index :incidents, :victim_id
21
+
22
+ create_table :victims do |t|
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ class Test::Unit::TestCase
29
+ def self.with_temp_db(&block)
30
+ include TempDB
31
+ @schema = Proc.new(&block) if block_given?
32
+ end
33
+
34
+ module TempDB
35
+ DB_PATH = "/tmp/%s.sqlite3"
36
+
37
+ def teardown_database!
38
+ File.delete(DB_PATH % [self.class.name])
39
+ end
40
+
41
+ def setup_database!
42
+ ActiveRecord::Base.establish_connection(
43
+ :adapter => "sqlite3",
44
+ :database => (DB_PATH % [self.class.name])
45
+ )
46
+ ActiveRecord::Base.logger = Logger.new(File.open("/dev/null", "w"))
47
+ @connection = ActiveRecord::Base.connection
48
+ end
49
+
50
+ def load_schema!(&block)
51
+ ActiveRecord::Schema.verbose = false
52
+ if block_given?
53
+ ActiveRecord::Schema.define(&block)
54
+ else
55
+ ActiveRecord::Schema.define(&self.class.class_eval{@schema})
56
+ end
57
+ end
58
+
59
+ def teardown
60
+ teardown_database!
61
+ end
62
+
63
+ def setup
64
+ setup_database!
65
+ load_schema!
66
+ end
67
+ end
68
+
69
+ def assert_array_equal(expected, actual, *args)
70
+ assert_equal(expected.sort, actual.sort, *args)
71
+ end
72
+
73
+ def assert_array_includes(*args)
74
+ message = "Expected <%s> to include <%s>"
75
+ expected = args.clone
76
+ actual = expected.pop
77
+
78
+ if actual.is_a? String
79
+ message = actual
80
+ actual = expected.pop
81
+ end
82
+
83
+ expected.each do |el|
84
+ assert actual.include?(el), (message % [actual.inspect, el.inspect])
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,12 @@
1
+ require File.join(File.dirname(__FILE__), "..", "test_helper")
2
+
3
+ class IndexesUnitTest < Test::Unit::TestCase
4
+ include CriminalDatabase
5
+ include ActiveRecord::Lint
6
+
7
+ def test_should_have_correct_indexes
8
+ scanner = Scanner.new(@connection)
9
+ assert_equal([Pair["incidents", "victim_id"]], scanner.indexes)
10
+ end
11
+
12
+ end
@@ -0,0 +1,27 @@
1
+ require File.join(File.dirname(__FILE__), "..", "test_helper")
2
+
3
+ class ModelScanningUnitTest < Test::Unit::TestCase
4
+ include CriminalDatabase
5
+ include ActiveRecord::Lint
6
+
7
+ def setup
8
+ ActiveRecord::Lint::unload_models
9
+ super
10
+ end
11
+
12
+ def test_should_have_correct_indexes
13
+ rails_root = File.join(File.dirname(__FILE__), "..", "fixtures", "criminals")
14
+ ActiveRecord::Lint::load_models(rails_root)
15
+
16
+ scanner = ActiveRecord::Lint::Scanner.new
17
+
18
+ expected = [
19
+ Pair["incidents", "victim_id"],
20
+ Pair["incidents", "criminal_id"],
21
+ Pair["incidents", "crime_id"]
22
+ ]
23
+
24
+ assert_array_equal(expected, scanner.foreign_keys)
25
+ end
26
+
27
+ end
@@ -0,0 +1,37 @@
1
+ require File.join(File.dirname(__FILE__), "..", "test_helper")
2
+
3
+ class PairUnitTest < Test::Unit::TestCase
4
+ include ActiveRecord::Lint
5
+ def test_comparison
6
+ assert_equal(Pair[1,2], Pair[1,2])
7
+ assert_equal(0, Pair[1,2] <=> Pair[1,2])
8
+ assert_equal(-1, Pair[0,2] <=> Pair[1,2])
9
+ assert_equal(1, Pair[2,2] <=> Pair[1,2])
10
+ assert_equal(-1, Pair[1,1] <=> Pair[1,2])
11
+ assert_equal(1, Pair[1,3] <=> Pair[1,2])
12
+
13
+ assert_not_equal(Pair[1,2], Pair[1,3])
14
+ assert_not_equal(Pair[1,2], Pair[2,2])
15
+ end
16
+
17
+ def test_subtraction_in_an_array
18
+ a1 = [Pair[1,2], Pair[2,2], Pair[1,1]]
19
+ a2 = [Pair[1,2], Pair[1,1]]
20
+ a3 = [Pair[2,2]]
21
+
22
+ assert_equal(a2, a1 - a3)
23
+ assert_equal(a3, a1 - a2)
24
+ assert_equal([], a1 - a2 - a3)
25
+ end
26
+
27
+ def test_hashes
28
+ assert_equal(Pair[1,2].hash, Pair[1,2].hash)
29
+ assert_equal(Pair[2,2].hash, Pair[2,2].hash)
30
+ assert_not_equal(Pair[1,2].hash, Pair[1,1].hash)
31
+ assert_not_equal(Pair[2,1].hash, Pair[1,1].hash)
32
+ end
33
+
34
+ def test_eql
35
+ assert(Pair[2,2].eql?(Pair[2,2]))
36
+ end
37
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cwninja-active_record_lint
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Tom Lea
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-01-08 00:00:00 -08:00
13
+ default_executable: arlint
14
+ dependencies: []
15
+
16
+ description: A library to support the automatic checking for the doing of stupid things with ActiveRecord.
17
+ email: commits@tomlea.co.uk
18
+ executables:
19
+ - arlint
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.markdown
24
+ files:
25
+ - Rakefile
26
+ - README.markdown
27
+ - lib/active_record/lint/memoize.rb
28
+ - lib/active_record/lint/pairs.rb
29
+ - lib/active_record/lint/reporter.rb
30
+ - lib/active_record/lint/scanner.rb
31
+ - lib/active_record/lint.rb
32
+ - lib/active_record_lint.rb
33
+ - test/fixtures/criminals/app/models/crime.rb
34
+ - test/fixtures/criminals/app/models/criminal.rb
35
+ - test/fixtures/criminals/app/models/incident.rb
36
+ - test/fixtures/criminals/app/models/victim.rb
37
+ - test/functional/missing_foreign_keys_test.rb
38
+ - test/functional/missing_indexes_test.rb
39
+ - test/functional/missing_tables_test.rb
40
+ - test/functional/reporter_test.rb
41
+ - test/test_helper.rb
42
+ - test/unit/indexes_test.rb
43
+ - test/unit/model_scanning_test.rb
44
+ - test/unit/pair_test.rb
45
+ - bin/arlint
46
+ has_rdoc: true
47
+ homepage: http://github.com/cwninja/active_record_lint
48
+ post_install_message:
49
+ rdoc_options:
50
+ - --line-numbers
51
+ - --inline-source
52
+ - --main
53
+ - README.markdown
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ requirements: []
69
+
70
+ rubyforge_project:
71
+ rubygems_version: 1.2.0
72
+ signing_key:
73
+ specification_version: 2
74
+ summary: Rails tool to find foreign keys without indexes and other common issues.
75
+ test_files:
76
+ - test/functional/missing_foreign_keys_test.rb
77
+ - test/functional/missing_indexes_test.rb
78
+ - test/functional/missing_tables_test.rb
79
+ - test/functional/reporter_test.rb
80
+ - test/unit/indexes_test.rb
81
+ - test/unit/model_scanning_test.rb
82
+ - test/unit/pair_test.rb