rails_best_practices 0.2.0 → 0.3.0

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.
Files changed (41) hide show
  1. data/README.textile +32 -14
  2. data/Rakefile +2 -2
  3. data/VERSION +1 -1
  4. data/lib/rails_best_practices/checks/add_model_virtual_attribute_check.rb +12 -7
  5. data/lib/rails_best_practices/checks/always_add_db_index_check.rb +90 -0
  6. data/lib/rails_best_practices/checks/check.rb +9 -3
  7. data/lib/rails_best_practices/checks/isolate_seed_data_check.rb +59 -0
  8. data/lib/rails_best_practices/checks/keep_finders_on_their_own_model_check.rb +29 -0
  9. data/lib/rails_best_practices/checks/law_of_demeter_check.rb +47 -0
  10. data/lib/rails_best_practices/checks/move_code_into_controller_check.rb +31 -0
  11. data/lib/rails_best_practices/checks/move_code_into_helper_check.rb +29 -0
  12. data/lib/rails_best_practices/checks/move_finder_to_named_scope_check.rb +1 -1
  13. data/lib/rails_best_practices/checks/move_model_logic_into_model_check.rb +1 -1
  14. data/lib/rails_best_practices/checks/replace_complex_creation_with_factory_method_check.rb +1 -1
  15. data/lib/rails_best_practices/checks/replace_instance_variable_with_local_variable_check.rb +23 -0
  16. data/lib/rails_best_practices/checks/use_filter_check.rb +38 -0
  17. data/lib/rails_best_practices/checks/use_observer_check.rb +49 -0
  18. data/lib/rails_best_practices/checks/use_scope_access_check.rb +3 -3
  19. data/lib/rails_best_practices/checks.rb +10 -1
  20. data/lib/rails_best_practices/command.rb +50 -5
  21. data/lib/rails_best_practices/core/core_ext.rb +12 -1
  22. data/lib/rails_best_practices/core/runner.rb +12 -3
  23. data/lib/rails_best_practices/core/visitable_sexp.rb +21 -5
  24. data/rails_best_practices.gemspec +43 -16
  25. data/rails_best_practices.yml +9 -0
  26. data/spec/rails_best_practices/checks/add_model_virtual_attribute_check_spec.rb +57 -4
  27. data/spec/rails_best_practices/checks/always_add_db_index_check_spec.rb +153 -0
  28. data/spec/rails_best_practices/checks/isolate_seed_data_check_spec.rb +79 -0
  29. data/spec/rails_best_practices/checks/keep_finders_on_their_own_model_check_spec.rb +71 -0
  30. data/spec/rails_best_practices/checks/law_of_demeter_check_spec.rb +37 -0
  31. data/spec/rails_best_practices/checks/move_code_into_controller_check_spec.rb +33 -0
  32. data/spec/rails_best_practices/checks/move_code_into_helper_check_spec.rb +29 -0
  33. data/spec/rails_best_practices/checks/move_finder_to_named_scope_check_spec.rb +6 -6
  34. data/spec/rails_best_practices/checks/move_model_logic_into_model_check_spec.rb +4 -4
  35. data/spec/rails_best_practices/checks/replace_complex_creation_with_factory_method_check_spec.rb +5 -5
  36. data/spec/rails_best_practices/checks/replace_instance_variable_with_local_variable_check_spec.rb +26 -0
  37. data/spec/rails_best_practices/checks/use_filter_check_spec.rb +85 -0
  38. data/spec/rails_best_practices/checks/use_model_association_check_spec.rb +6 -6
  39. data/spec/rails_best_practices/checks/use_observer_check_spec.rb +67 -0
  40. data/spec/rails_best_practices/checks/use_scope_access_check_spec.rb +17 -17
  41. metadata +38 -11
@@ -1,7 +1,7 @@
1
1
  require 'optparse'
2
2
 
3
3
  def expand_dirs_to_files *dirs
4
- extensions = ['rb']
4
+ extensions = ['rb', 'erb', 'builder']
5
5
 
6
6
  dirs.flatten.map { |p|
7
7
  if File.directory? p
@@ -9,13 +9,46 @@ def expand_dirs_to_files *dirs
9
9
  else
10
10
  p
11
11
  end
12
- }.flatten.sort
12
+ }.flatten
13
+ end
14
+
15
+ # for law_of_demeter_check
16
+ def model_first_sort files
17
+ files.sort { |a, b|
18
+ if a =~ /models\/.*rb/
19
+ -1
20
+ elsif b =~ /models\/.*rb/
21
+ 1
22
+ else
23
+ a <=> b
24
+ end
25
+ }
26
+ end
27
+
28
+ # for always_add_db_index_check
29
+ def add_duplicate_migrations files
30
+ migration_files = files.select { |file| file.index("db/migrate") }
31
+ (files << migration_files).flatten
32
+ end
33
+
34
+ def ignore_files files, pattern
35
+ files.reject { |file| file.index(pattern) }
13
36
  end
14
37
 
15
38
  options = {}
16
39
  OptionParser.new do |opts|
17
40
  opts.banner = "Usage: rails_best_practices [options]"
18
41
 
42
+ opts.on("-d", "--debug", "Debug mode") do
43
+ options['debug'] = true
44
+ end
45
+
46
+ ['vendor', 'spec', 'test', 'stories'].each do |pattern|
47
+ opts.on("--#{pattern}", "include #{pattern} files") do
48
+ options[pattern] = true
49
+ end
50
+ end
51
+
19
52
  opts.on_tail("-h", "--help", "Show this message") do
20
53
  puts opts
21
54
  exit
@@ -25,8 +58,20 @@ OptionParser.new do |opts|
25
58
  end
26
59
 
27
60
  runner = RailsBestPractices::Core::Runner.new
28
- expand_dirs_to_files(ARGV).each.each { |file| runner.check_file(file) }
61
+ runner.set_debug if options['debug']
62
+
63
+ files = expand_dirs_to_files(ARGV)
64
+ files = model_first_sort(files)
65
+ files = add_duplicate_migrations(files)
66
+ ['vendor', 'spec', 'test', 'stories'].each do |pattern|
67
+ files = ignore_files(files, "#{pattern}/") unless options[pattern]
68
+ end
69
+ files.each { |file| runner.check_file(file) }
70
+
29
71
  runner.errors.each {|error| puts error}
30
- puts "\nFound #{runner.errors.size} errors."
72
+ if runner.errors.size > 0
73
+ puts "\ngo to http://wiki.github.com/flyerhzm/rails_best_practices to see how to solve these errors."
74
+ puts "\nFound #{runner.errors.size} errors."
75
+ end
31
76
 
32
- exit runner.errors.size
77
+ exit runner.errors.size
@@ -4,8 +4,19 @@ module Enumerable
4
4
  end
5
5
  end
6
6
 
7
+ class String
8
+ # copy from rails
9
+ def underscore
10
+ self.gsub(/::/, '/').
11
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
12
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
13
+ tr("-", "_").
14
+ downcase
15
+ end
16
+ end
17
+
7
18
  class NilClass
8
19
  def method_missing(method_sym, *arguments, &block)
9
20
  return nil
10
21
  end
11
- end
22
+ end
@@ -1,5 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'ruby_parser'
3
+ require 'erb'
3
4
  require 'yaml'
4
5
 
5
6
  module RailsBestPractices
@@ -17,10 +18,17 @@ module RailsBestPractices
17
18
  @checks = checks unless checks.empty?
18
19
  @checks ||= load_checks
19
20
  @checker ||= CheckingVisitor.new(@checks)
20
- @parser = RubyParser.new
21
+ @debug = false
22
+ end
23
+
24
+ def set_debug
25
+ @debug = true
21
26
  end
22
27
 
23
28
  def check(filename, content)
29
+ if filename =~ /.*erb/
30
+ content = ERB.new(content).src
31
+ end
24
32
  node = parse(filename, content)
25
33
  node.accept(@checker) if node
26
34
  end
@@ -42,10 +50,11 @@ module RailsBestPractices
42
50
  private
43
51
 
44
52
  def parse(filename, content)
53
+ puts filename if @debug
45
54
  begin
46
- @parser.parse(content, filename)
55
+ RubyParser.new.parse(content, filename)
47
56
  rescue Exception => e
48
- puts "#{filename} looks like it's not a valid Ruby file. Skipping..." if ENV["ROODI_DEBUG"]
57
+ puts "#{filename} looks like it's not a valid Ruby file. Skipping..." if @debug
49
58
  nil
50
59
  end
51
60
  end
@@ -47,13 +47,13 @@ class Sexp
47
47
  end
48
48
 
49
49
  def subject
50
- if [:attrasgn, :call, :iasgn, :lasgn].include? node_type
50
+ if [:attrasgn, :call, :iasgn, :lasgn, :class].include? node_type
51
51
  self[1]
52
52
  end
53
53
  end
54
54
 
55
55
  def message
56
- if [:attrasgn, :call].include? node_type
56
+ if [:attrasgn, :call, :defs].include? node_type
57
57
  self[2]
58
58
  end
59
59
  end
@@ -81,15 +81,31 @@ class Sexp
81
81
  self[3]
82
82
  end
83
83
  end
84
+
85
+ def message_name
86
+ if :defn == node_type
87
+ self[1]
88
+ end
89
+ end
84
90
 
85
- def method_body
91
+ def body
86
92
  if :block == node_type
87
93
  self[1..-1]
88
- else
94
+ elsif :class == node_type
95
+ self[3]
96
+ elsif :defn == node_type
97
+ self[3][1]
98
+ elsif :defs == node_type
99
+ self[4][1]
89
100
  end
90
101
  end
91
102
 
92
103
  def to_ruby
93
- Ruby2Ruby.new.process(self)
104
+ Ruby2Ruby.new.process(self) unless self.empty?
105
+ end
106
+
107
+ def to_ruby_string
108
+ return nil if self.empty?
109
+ eval(Ruby2Ruby.new.process(self)).to_s
94
110
  end
95
111
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rails_best_practices}
8
- s.version = "0.2.0"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Richard Huang"]
12
- s.date = %q{2009-11-06}
12
+ s.date = %q{2009-11-10}
13
13
  s.default_executable = %q{rails_best_practices}
14
14
  s.description = %q{check rails files according to ihower's presentation 'rails best practices'}
15
15
  s.email = %q{flyerhzm@gmail.com}
@@ -28,8 +28,14 @@ Gem::Specification.new do |s|
28
28
  "lib/rails_best_practices.rb",
29
29
  "lib/rails_best_practices/checks.rb",
30
30
  "lib/rails_best_practices/checks/add_model_virtual_attribute_check.rb",
31
+ "lib/rails_best_practices/checks/always_add_db_index_check.rb",
31
32
  "lib/rails_best_practices/checks/check.rb",
33
+ "lib/rails_best_practices/checks/isolate_seed_data_check.rb",
34
+ "lib/rails_best_practices/checks/keep_finders_on_their_own_model_check.rb",
35
+ "lib/rails_best_practices/checks/law_of_demeter_check.rb",
32
36
  "lib/rails_best_practices/checks/many_to_many_collection_check.rb",
37
+ "lib/rails_best_practices/checks/move_code_into_controller_check.rb",
38
+ "lib/rails_best_practices/checks/move_code_into_helper_check.rb",
33
39
  "lib/rails_best_practices/checks/move_finder_to_named_scope_check.rb",
34
40
  "lib/rails_best_practices/checks/move_model_logic_into_model_check.rb",
35
41
  "lib/rails_best_practices/checks/needless_deep_nesting_check.rb",
@@ -37,8 +43,11 @@ Gem::Specification.new do |s|
37
43
  "lib/rails_best_practices/checks/not_use_default_route_check.rb",
38
44
  "lib/rails_best_practices/checks/overuse_route_customizations_check.rb",
39
45
  "lib/rails_best_practices/checks/replace_complex_creation_with_factory_method_check.rb",
46
+ "lib/rails_best_practices/checks/replace_instance_variable_with_local_variable_check.rb",
47
+ "lib/rails_best_practices/checks/use_filter_check.rb",
40
48
  "lib/rails_best_practices/checks/use_model_association_check.rb",
41
49
  "lib/rails_best_practices/checks/use_model_callback_check.rb",
50
+ "lib/rails_best_practices/checks/use_observer_check.rb",
42
51
  "lib/rails_best_practices/checks/use_scope_access_check.rb",
43
52
  "lib/rails_best_practices/command.rb",
44
53
  "lib/rails_best_practices/core.rb",
@@ -50,7 +59,13 @@ Gem::Specification.new do |s|
50
59
  "rails_best_practices.gemspec",
51
60
  "rails_best_practices.yml",
52
61
  "spec/rails_best_practices/checks/add_model_virtual_attribute_check_spec.rb",
62
+ "spec/rails_best_practices/checks/always_add_db_index_check_spec.rb",
63
+ "spec/rails_best_practices/checks/isolate_seed_data_check_spec.rb",
64
+ "spec/rails_best_practices/checks/keep_finders_on_their_own_model_check_spec.rb",
65
+ "spec/rails_best_practices/checks/law_of_demeter_check_spec.rb",
53
66
  "spec/rails_best_practices/checks/many_to_many_collection_check_spec.rb",
67
+ "spec/rails_best_practices/checks/move_code_into_controller_check_spec.rb",
68
+ "spec/rails_best_practices/checks/move_code_into_helper_check_spec.rb",
54
69
  "spec/rails_best_practices/checks/move_finder_to_named_scope_check_spec.rb",
55
70
  "spec/rails_best_practices/checks/move_model_logic_into_model_check_spec.rb",
56
71
  "spec/rails_best_practices/checks/needless_deep_nesting_check_spec.rb",
@@ -58,8 +73,11 @@ Gem::Specification.new do |s|
58
73
  "spec/rails_best_practices/checks/not_use_default_route_check_spec.rb",
59
74
  "spec/rails_best_practices/checks/overuse_route_customizations_check_spec.rb",
60
75
  "spec/rails_best_practices/checks/replace_complex_creation_with_factory_method_check_spec.rb",
76
+ "spec/rails_best_practices/checks/replace_instance_variable_with_local_variable_check_spec.rb",
77
+ "spec/rails_best_practices/checks/use_filter_check_spec.rb",
61
78
  "spec/rails_best_practices/checks/use_model_association_check_spec.rb",
62
79
  "spec/rails_best_practices/checks/use_model_callback_check_spec.rb",
80
+ "spec/rails_best_practices/checks/use_observer_check_spec.rb",
63
81
  "spec/rails_best_practices/checks/use_scope_access_check_spec.rb",
64
82
  "spec/spec.opts",
65
83
  "spec/spec_helper.rb"
@@ -70,18 +88,27 @@ Gem::Specification.new do |s|
70
88
  s.rubygems_version = %q{1.3.5}
71
89
  s.summary = %q{check rails files according to ihower's presentation 'rails best practices'}
72
90
  s.test_files = [
73
- "spec/rails_best_practices/checks/use_scope_access_check_spec.rb",
74
- "spec/rails_best_practices/checks/not_use_default_route_check_spec.rb",
75
- "spec/rails_best_practices/checks/add_model_virtual_attribute_check_spec.rb",
76
- "spec/rails_best_practices/checks/use_model_callback_check_spec.rb",
91
+ "spec/rails_best_practices/checks/add_model_virtual_attribute_check_spec.rb",
92
+ "spec/rails_best_practices/checks/always_add_db_index_check_spec.rb",
93
+ "spec/rails_best_practices/checks/isolate_seed_data_check_spec.rb",
94
+ "spec/rails_best_practices/checks/keep_finders_on_their_own_model_check_spec.rb",
95
+ "spec/rails_best_practices/checks/law_of_demeter_check_spec.rb",
77
96
  "spec/rails_best_practices/checks/many_to_many_collection_check_spec.rb",
78
- "spec/rails_best_practices/checks/use_model_association_check_spec.rb",
79
- "spec/rails_best_practices/checks/move_model_logic_into_model_check_spec.rb",
80
- "spec/rails_best_practices/checks/replace_complex_creation_with_factory_method_check_spec.rb",
81
- "spec/rails_best_practices/checks/nested_model_forms_check_spec.rb",
97
+ "spec/rails_best_practices/checks/move_code_into_controller_check_spec.rb",
98
+ "spec/rails_best_practices/checks/move_code_into_helper_check_spec.rb",
82
99
  "spec/rails_best_practices/checks/move_finder_to_named_scope_check_spec.rb",
100
+ "spec/rails_best_practices/checks/move_model_logic_into_model_check_spec.rb",
83
101
  "spec/rails_best_practices/checks/needless_deep_nesting_check_spec.rb",
102
+ "spec/rails_best_practices/checks/nested_model_forms_check_spec.rb",
103
+ "spec/rails_best_practices/checks/not_use_default_route_check_spec.rb",
84
104
  "spec/rails_best_practices/checks/overuse_route_customizations_check_spec.rb",
105
+ "spec/rails_best_practices/checks/replace_complex_creation_with_factory_method_check_spec.rb",
106
+ "spec/rails_best_practices/checks/replace_instance_variable_with_local_variable_check_spec.rb",
107
+ "spec/rails_best_practices/checks/use_filter_check_spec.rb",
108
+ "spec/rails_best_practices/checks/use_model_association_check_spec.rb",
109
+ "spec/rails_best_practices/checks/use_model_callback_check_spec.rb",
110
+ "spec/rails_best_practices/checks/use_observer_check_spec.rb",
111
+ "spec/rails_best_practices/checks/use_scope_access_check_spec.rb",
85
112
  "spec/spec_helper.rb"
86
113
  ]
87
114
 
@@ -90,15 +117,15 @@ Gem::Specification.new do |s|
90
117
  s.specification_version = 3
91
118
 
92
119
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
93
- s.add_runtime_dependency(%q<ruby_parser>, [">= 0"])
94
- s.add_runtime_dependency(%q<ruby2ruby>, [">= 0"])
120
+ s.add_runtime_dependency(%q<ruby_parser>, [">= 2.0.4"])
121
+ s.add_runtime_dependency(%q<ruby2ruby>, [">= 1.2.4"])
95
122
  else
96
- s.add_dependency(%q<ruby_parser>, [">= 0"])
97
- s.add_dependency(%q<ruby2ruby>, [">= 0"])
123
+ s.add_dependency(%q<ruby_parser>, [">= 2.0.4"])
124
+ s.add_dependency(%q<ruby2ruby>, [">= 1.2.4"])
98
125
  end
99
126
  else
100
- s.add_dependency(%q<ruby_parser>, [">= 0"])
101
- s.add_dependency(%q<ruby2ruby>, [">= 0"])
127
+ s.add_dependency(%q<ruby_parser>, [">= 2.0.4"])
128
+ s.add_dependency(%q<ruby2ruby>, [">= 1.2.4"])
102
129
  end
103
130
  end
104
131
 
@@ -10,3 +10,12 @@ MoveModelLogicIntoModelCheck: { called_count: 4 }
10
10
  OveruseRouteCustomizationsCheck: { customize_count: 3 }
11
11
  NeedlessDeepNestingCheck: { nested_count: 2 }
12
12
  NotUseDefaultRouteCheck: { }
13
+ KeepFindersOnTheirOwnModelCheck: { }
14
+ LawOfDemeterCheck: { }
15
+ UseObserverCheck: { }
16
+ IsolateSeedDataCheck: { }
17
+ AlwaysAddDbIndexCheck: { }
18
+ UseFilterCheck: { }
19
+ MoveCodeIntoControllerCheck: { }
20
+ MoveCodeIntoHelperCheck: { }
21
+ ReplaceInstanceVariableWithLocalVariableCheck: { }
@@ -17,10 +17,28 @@ describe RailsBestPractices::Checks::AddModelVirtualAttributeCheck do
17
17
  end
18
18
  end
19
19
  EOF
20
- @runner.check('app/controller/users_controller.rb', content)
20
+ @runner.check('app/controllers/users_controller.rb', content)
21
21
  errors = @runner.errors
22
22
  errors.should_not be_empty
23
- errors[0].to_s.should == "app/controller/users_controller.rb:3 - add model virtual attribute (for @user)"
23
+ errors[0].to_s.should == "app/controllers/users_controller.rb:3 - add model virtual attribute (for @user)"
24
+ end
25
+
26
+ it "should add model virtual attribute with local assignment" do
27
+ content = <<-EOF
28
+ class UsersController < ApplicationController
29
+
30
+ def create
31
+ user = User.new(params[:user])
32
+ user.first_name = params[:full_name].split(' ', 2).first
33
+ user.last_name = params[:full_name].split(' ', 2).last
34
+ user.save
35
+ end
36
+ end
37
+ EOF
38
+ @runner.check('app/controllers/users_controller.rb', content)
39
+ errors = @runner.errors
40
+ errors.should_not be_empty
41
+ errors[0].to_s.should == "app/controllers/users_controller.rb:3 - add model virtual attribute (for user)"
24
42
  end
25
43
 
26
44
  it "should not add model virtual attribute with differen param" do
@@ -35,7 +53,7 @@ describe RailsBestPractices::Checks::AddModelVirtualAttributeCheck do
35
53
  end
36
54
  end
37
55
  EOF
38
- @runner.check('app/controller/users_controller.rb', content)
56
+ @runner.check('app/controllers/users_controller.rb', content)
39
57
  errors = @runner.errors
40
58
  errors.should be_empty
41
59
  end
@@ -53,7 +71,42 @@ describe RailsBestPractices::Checks::AddModelVirtualAttributeCheck do
53
71
  end
54
72
  end
55
73
  EOF
56
- @runner.check('app/controller/users_controller.rb', content)
74
+ @runner.check('app/controllers/users_controller.rb', content)
75
+ errors = @runner.errors
76
+ errors.should be_empty
77
+ end
78
+
79
+ it "should add model virtual attribute with two dimension params" do
80
+ content = <<-EOF
81
+ class UsersController < ApplicationController
82
+
83
+ def create
84
+ @user = User.new(params[:user])
85
+ @user.first_name = params[:user][:full_name].split(' ', 2).first
86
+ @user.last_name = params[:user][:full_name].split(' ', 2).last
87
+ @user.save
88
+ end
89
+ end
90
+ EOF
91
+ @runner.check('app/controllers/users_controller.rb', content)
92
+ errors = @runner.errors
93
+ errors.should_not be_empty
94
+ errors[0].to_s.should == "app/controllers/users_controller.rb:3 - add model virtual attribute (for @user)"
95
+ end
96
+
97
+ it "should no add model virtual attribute with two dimension params" do
98
+ content = <<-EOF
99
+ class UsersController < ApplicationController
100
+
101
+ def create
102
+ @user = User.new(params[:user])
103
+ @user.first_name = params[:user][:first_name]
104
+ @user.last_name = params[:user][:last_name]
105
+ @user.save
106
+ end
107
+ end
108
+ EOF
109
+ @runner.check('app/controllers/users_controller.rb', content)
57
110
  errors = @runner.errors
58
111
  errors.should be_empty
59
112
  end
@@ -0,0 +1,153 @@
1
+ require File.join(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe RailsBestPractices::Checks::AlwaysAddDbIndexCheck do
4
+ before(:each) do
5
+ @runner = RailsBestPractices::Core::Runner.new(RailsBestPractices::Checks::AlwaysAddDbIndexCheck.new)
6
+ end
7
+
8
+ it "should always add db index" do
9
+ content = <<-EOF
10
+ class CreateComments < ActiveRecord::Migration
11
+ def self.up
12
+ create_table "comments", :force => true do |t|
13
+ t.string :content
14
+ t.integer :post_id
15
+ t.integer :user_id
16
+ end
17
+ end
18
+
19
+ def self.down
20
+ drop_table "comments"
21
+ end
22
+ end
23
+ EOF
24
+ @runner.check('db/migrate/20090918130258_create_comments.rb', content)
25
+ @runner.check('db/migrate/20090918130258_create_comments.rb', content)
26
+ errors = @runner.errors
27
+ errors.should_not be_empty
28
+ errors[0].to_s.should == "db/migrate/20090918130258_create_comments.rb:2 - always add db index (comments => post_id, comments => user_id)"
29
+ end
30
+
31
+ it "should always add db index with column has no id" do
32
+ content = <<-EOF
33
+ class CreateComments < ActiveRecord::Migration
34
+ def self.up
35
+ create_table "comments", :force => true do |t|
36
+ t.string :content
37
+ t.integer :position
38
+ end
39
+ end
40
+
41
+ def self.down
42
+ drop_table "comments"
43
+ end
44
+ end
45
+ EOF
46
+ @runner.check('db/migrate/20090918130258_create_comments.rb', content)
47
+ @runner.check('db/migrate/20090918130258_create_comments.rb', content)
48
+ errors = @runner.errors
49
+ errors.should be_empty
50
+ end
51
+
52
+ it "should always add db index with references" do
53
+ content = <<-EOF
54
+ class CreateComments < ActiveRecord::Migration
55
+ def self.up
56
+ create_table "comments", :force => true do |t|
57
+ t.string :content
58
+ t.references :post
59
+ t.references :user
60
+ end
61
+ end
62
+
63
+ def self.down
64
+ drop_table "comments"
65
+ end
66
+ end
67
+ EOF
68
+ @runner.check('db/migrate/20090918130258_create_comments.rb', content)
69
+ @runner.check('db/migrate/20090918130258_create_comments.rb', content)
70
+ errors = @runner.errors
71
+ errors.should_not be_empty
72
+ errors[0].to_s.should == "db/migrate/20090918130258_create_comments.rb:2 - always add db index (comments => post_id, comments => user_id)"
73
+ end
74
+
75
+ it "should always add db index with column" do
76
+ content = <<-EOF
77
+ class CreateComments < ActiveRecord::Migration
78
+ def self.up
79
+ create_table "comments", :force => true do |t|
80
+ t.string :content
81
+ t.column :post_id, :integer
82
+ t.column :user_id, :integer
83
+ end
84
+ end
85
+
86
+ def self.down
87
+ drop_table "comments"
88
+ end
89
+ end
90
+ EOF
91
+ @runner.check('db/migrate/20090918130258_create_comments.rb', content)
92
+ @runner.check('db/migrate/20090918130258_create_comments.rb', content)
93
+ errors = @runner.errors
94
+ errors.should_not be_empty
95
+ errors[0].to_s.should == "db/migrate/20090918130258_create_comments.rb:2 - always add db index (comments => post_id, comments => user_id)"
96
+ end
97
+
98
+ it "should not always add db index with add_index" do
99
+ content = <<-EOF
100
+ class CreateComments < ActiveRecord::Migration
101
+ def self.up
102
+ create_table "comments", :force => true do |t|
103
+ t.string :content
104
+ t.integer :post_id
105
+ t.integer :user_id
106
+ end
107
+
108
+ add_index :comments, :post_id
109
+ add_index :comments, :user_id
110
+ end
111
+
112
+ def self.down
113
+ drop_table "comments"
114
+ end
115
+ end
116
+ EOF
117
+ @runner.check('db/migrate/20090918130258_create_comments.rb', content)
118
+ @runner.check('db/migrate/20090918130258_create_comments.rb', content)
119
+ errors = @runner.errors
120
+ errors.should be_empty
121
+ end
122
+
123
+ it "should not always add db index with add_index in another migration file" do
124
+ content = <<-EOF
125
+ class CreateComments < ActiveRecord::Migration
126
+ def self.up
127
+ create_table "comments", :force => true do |t|
128
+ t.string :content
129
+ t.integer :post_id
130
+ t.integer :user_id
131
+ end
132
+ end
133
+
134
+ def self.down
135
+ drop_table "comments"
136
+ end
137
+ end
138
+ EOF
139
+ add_index_content = <<-EOF
140
+ class AddIndexesToComments < ActiveRecord::Migration
141
+ def self.up
142
+ add_index :comments, :post_id
143
+ add_index :comments, :user_id
144
+ end
145
+ end
146
+ EOF
147
+ @runner.check('db/migrate/20090918130258_create_comments.rb', content)
148
+ @runner.check('db/migrate/20090919130258_add_indexes_to_comments.rb', content)
149
+ @runner.check('db/migrate/20090918130258_create_comments.rb', content)
150
+ @runner.check('db/migrate/20090919130258_add_indexes_to_comments.rb', content)
151
+ errors = @runner.errors
152
+ end
153
+ end
@@ -0,0 +1,79 @@
1
+ require File.join(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe RailsBestPractices::Checks::IsolateSeedDataCheck do
4
+ before(:each) do
5
+ @runner = RailsBestPractices::Core::Runner.new(RailsBestPractices::Checks::IsolateSeedDataCheck.new)
6
+ end
7
+
8
+ it "should isolate seed data" do
9
+ content = <<-EOF
10
+ class CreateRoles < ActiveRecord::Migration
11
+ def self.up
12
+ create_table "roles", :force => true do |t|
13
+ t.string :name
14
+ end
15
+
16
+ ["admin", "author", "editor", "account"].each do |name|
17
+ Role.create!(:name => name)
18
+ end
19
+ end
20
+
21
+ def self.down
22
+ drop_table "roles"
23
+ end
24
+ end
25
+ EOF
26
+ @runner.check('db/migrate/20090818130258_create_roles.rb', content)
27
+ @runner.check('db/migrate/20090818130258_create_roles.rb', content)
28
+ errors = @runner.errors
29
+ errors.should_not be_empty
30
+ errors[0].to_s.should == "db/migrate/20090818130258_create_roles.rb:8 - isolate seed data"
31
+ errors.size.should == 1
32
+ end
33
+
34
+ it "should isolate seed data with new and save" do
35
+ content = <<-EOF
36
+ class CreateRoles < ActiveRecord::Migration
37
+ def self.up
38
+ create_table "roles", :force => true do |t|
39
+ t.string :name
40
+ end
41
+
42
+ ["admin", "author", "editor", "account"].each do |name|
43
+ role = Role.new(:name => name)
44
+ role.save!
45
+ end
46
+ end
47
+
48
+ def self.down
49
+ drop_table "roles"
50
+ end
51
+ end
52
+ EOF
53
+ @runner.check('db/migrate/20090818130258_create_roles.rb', content)
54
+ @runner.check('db/migrate/20090818130258_create_roles.rb', content)
55
+ errors = @runner.errors
56
+ errors.should_not be_empty
57
+ errors[0].to_s.should == "db/migrate/20090818130258_create_roles.rb:9 - isolate seed data"
58
+ end
59
+
60
+ it "should not isolate seed data without data insert" do
61
+ content = <<-EOF
62
+ class CreateRoles < ActiveRecord::Migration
63
+ def self.up
64
+ create_table "roles", :force => true do |t|
65
+ t.string :name
66
+ end
67
+ end
68
+
69
+ def self.down
70
+ drop_table "roles"
71
+ end
72
+ end
73
+ EOF
74
+ @runner.check('db/migrate/20090818130258_create_roles.rb', content)
75
+ @runner.check('db/migrate/20090818130258_create_roles.rb', content)
76
+ errors = @runner.errors
77
+ errors.should be_empty
78
+ end
79
+ end