rails_best_practices 0.6.1 → 0.6.5

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 (46) hide show
  1. data/.gitignore +12 -0
  2. data/.rspec.example +2 -0
  3. data/.rvmrc.example +2 -0
  4. data/.watchr +65 -0
  5. data/.watchr.example +65 -0
  6. data/Gemfile +3 -0
  7. data/README.md +6 -0
  8. data/Rakefile +45 -0
  9. data/assets/result.html.haml +53 -0
  10. data/lib/rails_best_practices.rb +30 -11
  11. data/lib/rails_best_practices/checks/check.rb +10 -10
  12. data/lib/rails_best_practices/command.rb +9 -0
  13. data/lib/rails_best_practices/core/visitable_sexp.rb +9 -10
  14. data/lib/rails_best_practices/version.rb +1 -1
  15. data/rails_best_practices.gemspec +32 -0
  16. data/rubies_test.sh +10 -0
  17. data/spec/rails_best_practices/checks/add_model_virtual_attribute_check_spec.rb +113 -0
  18. data/spec/rails_best_practices/checks/always_add_db_index_check_spec.rb +172 -0
  19. data/spec/rails_best_practices/checks/check_spec.rb +57 -0
  20. data/spec/rails_best_practices/checks/dry_bundler_in_capistrano_check_spec.rb +39 -0
  21. data/spec/rails_best_practices/checks/isolate_seed_data_check_spec.rb +105 -0
  22. data/spec/rails_best_practices/checks/keep_finders_on_their_own_model_check_spec.rb +103 -0
  23. data/spec/rails_best_practices/checks/law_of_demeter_check_spec.rb +101 -0
  24. data/spec/rails_best_practices/checks/move_code_into_controller_check_spec.rb +33 -0
  25. data/spec/rails_best_practices/checks/move_code_into_helper_check_spec.rb +28 -0
  26. data/spec/rails_best_practices/checks/move_code_into_model_check_spec.rb +55 -0
  27. data/spec/rails_best_practices/checks/move_finder_to_named_scope_check_spec.rb +82 -0
  28. data/spec/rails_best_practices/checks/move_model_logic_into_model_check_spec.rb +49 -0
  29. data/spec/rails_best_practices/checks/needless_deep_nesting_check_spec.rb +140 -0
  30. data/spec/rails_best_practices/checks/not_use_default_route_check_spec.rb +63 -0
  31. data/spec/rails_best_practices/checks/overuse_route_customizations_check_spec.rb +159 -0
  32. data/spec/rails_best_practices/checks/replace_complex_creation_with_factory_method_check_spec.rb +76 -0
  33. data/spec/rails_best_practices/checks/replace_instance_variable_with_local_variable_check_spec.rb +36 -0
  34. data/spec/rails_best_practices/checks/use_before_filter_check_spec.rb +85 -0
  35. data/spec/rails_best_practices/checks/use_model_association_check_spec.rb +71 -0
  36. data/spec/rails_best_practices/checks/use_observer_check_spec.rb +155 -0
  37. data/spec/rails_best_practices/checks/use_query_attribute_check_spec.rb +192 -0
  38. data/spec/rails_best_practices/checks/use_say_with_time_in_migrations_check_spec.rb +113 -0
  39. data/spec/rails_best_practices/checks/use_scope_access_check_spec.rb +193 -0
  40. data/spec/rails_best_practices/core/error_spec.rb +7 -0
  41. data/spec/rails_best_practices/core/visitable_sexp_spec.rb +259 -0
  42. data/spec/rails_best_practices/core_ext/enumerable_spec.rb +7 -0
  43. data/spec/rails_best_practices/core_ext/nil_class_spec.rb +11 -0
  44. data/spec/rails_best_practices_spec.rb +44 -0
  45. data/spec/spec_helper.rb +4 -0
  46. metadata +114 -32
@@ -0,0 +1,103 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsBestPractices::Checks::KeepFindersOnTheirOwnModelCheck do
4
+ before(:each) do
5
+ @runner = RailsBestPractices::Core::Runner.new(RailsBestPractices::Checks::KeepFindersOnTheirOwnModelCheck.new)
6
+ end
7
+
8
+ it "should keep finders on thier own model" do
9
+ content = <<-EOF
10
+ class Post < ActiveRecord::Base
11
+ has_many :comments
12
+
13
+ def find_valid_comments
14
+ self.comment.find(:all, :conditions => { :is_spam => false },
15
+ :limit => 10)
16
+ end
17
+ end
18
+ EOF
19
+ @runner.review('app/models/post.rb', content)
20
+ errors = @runner.errors
21
+ errors.should_not be_empty
22
+ errors[0].to_s.should == "app/models/post.rb:5 - keep finders on their own model"
23
+ end
24
+
25
+ it "should keep finders on thier own model with all method" do
26
+ content = <<-EOF
27
+ class Post < ActiveRecord::Base
28
+ has_many :comments
29
+
30
+ def find_valid_comments
31
+ self.comment.all(:conditions => { :is_spam => false },
32
+ :limit => 10)
33
+ end
34
+ end
35
+ EOF
36
+ @runner.review('app/models/post.rb', content)
37
+ errors = @runner.errors
38
+ errors.should_not be_empty
39
+ errors[0].to_s.should == "app/models/post.rb:5 - keep finders on their own model"
40
+ end
41
+
42
+ it "should not keep finders on thier own model with self finder" do
43
+ content = <<-EOF
44
+ class Post < ActiveRecord::Base
45
+ has_many :comments
46
+
47
+ def find_valid_comments
48
+ self.find(:all, :conditions => { :is_spam => false },
49
+ :limit => 10)
50
+ end
51
+ end
52
+ EOF
53
+ @runner.review('app/models/post.rb', content)
54
+ errors = @runner.errors
55
+ errors.should be_empty
56
+ end
57
+
58
+ it "should not keep finders on thier own model with own finder" do
59
+ content = <<-EOF
60
+ class Post < ActiveRecord::Base
61
+ has_many :comments
62
+
63
+ def find_valid_comments
64
+ Post.find(:all, :conditions => { :is_spam => false },
65
+ :limit => 10)
66
+ end
67
+ end
68
+ EOF
69
+ @runner.review('app/models/post.rb', content)
70
+ errors = @runner.errors
71
+ errors.should be_empty
72
+ end
73
+
74
+ it "should not keep finders on their own model without finder" do
75
+ content = <<-EOF
76
+ class Post < ActiveRecord::Base
77
+ has_many :comments
78
+
79
+ def find_valid_comments
80
+ self.comments.destroy_all
81
+ end
82
+ end
83
+ EOF
84
+ @runner.review('app/models/post.rb', content)
85
+ errors = @runner.errors
86
+ errors.should be_empty
87
+ end
88
+
89
+ it "should not keep finders on their own model with ruby Array#find" do
90
+ content = <<-EOF
91
+ class Post < ActiveRecord::Base
92
+ has_many :comments
93
+
94
+ def active_comments
95
+ self.comments.find {|comment| comment.status == 'active'}
96
+ end
97
+ end
98
+ EOF
99
+ @runner.review('app/models/post.rb', content)
100
+ errors = @runner.errors
101
+ errors.should be_empty
102
+ end
103
+ end
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsBestPractices::Checks::LawOfDemeterCheck do
4
+
5
+ before :each do
6
+ @runner = RailsBestPractices::Core::Runner.new(RailsBestPractices::Checks::LawOfDemeterCheck.new)
7
+ end
8
+
9
+ describe "belongs_to" do
10
+ before(:each) do
11
+ content = <<-EOF
12
+ class Invoice < ActiveRecord::Base
13
+ belongs_to :user
14
+ end
15
+ EOF
16
+ @runner.prepare('app/models/invoice.rb', content)
17
+ end
18
+
19
+ it "should law of demeter" do
20
+ content = <<-EOF
21
+ <%= @invoice.user.name %>
22
+ <%= @invoice.user.address %>
23
+ <%= @invoice.user.cellphone %>
24
+ EOF
25
+ @runner.review('app/views/invoices/show.html.erb', content)
26
+ errors = @runner.errors
27
+ errors.should_not be_empty
28
+ errors[0].to_s.should == "app/views/invoices/show.html.erb:1 - law of demeter"
29
+ end
30
+
31
+ it "should law of demeter" do
32
+ content = <<-EOF
33
+ = @invoice.user.name
34
+ = @invoice.user.address
35
+ = @invoice.user.cellphone
36
+ EOF
37
+ @runner.review('app/views/invoices/show.html.haml', content)
38
+ errors = @runner.errors
39
+ errors.should_not be_empty
40
+ errors[0].to_s.should == "app/views/invoices/show.html.haml:1 - law of demeter"
41
+ end
42
+
43
+ it "should no law of demeter" do
44
+ content = <<-EOF
45
+ <%= @invoice.user_name %>
46
+ <%= @invoice.user_address %>
47
+ <%= @invoice.user_cellphone %>
48
+ EOF
49
+ @runner.review('app/views/invoices/show.html.erb', content)
50
+ errors = @runner.errors
51
+ errors.should be_empty
52
+ end
53
+ end
54
+
55
+ describe "has_one" do
56
+ before(:each) do
57
+ content = <<-EOF
58
+ class Invoice < ActiveRecord::Base
59
+ has_one :price
60
+ end
61
+ EOF
62
+ @runner.prepare('app/models/invoice.rb', content)
63
+ end
64
+
65
+ it "should law of demeter" do
66
+ content = <<-EOF
67
+ <%= @invoice.price.currency %>
68
+ <%= @invoice.price.number %>
69
+ EOF
70
+ @runner.review('app/views/invoices/show.html.erb', content)
71
+ errors = @runner.errors
72
+ errors.should_not be_empty
73
+ errors[0].to_s.should == "app/views/invoices/show.html.erb:1 - law of demeter"
74
+ end
75
+ end
76
+
77
+ it "should no law of demeter with method call" do
78
+ content = <<-EOF
79
+ class Question < ActiveRecord::Base
80
+ has_many :answers, :dependent => :destroy
81
+ end
82
+ EOF
83
+ @runner.prepare('app/models/question.rb', content)
84
+ content = <<-EOF
85
+ class Answer < ActiveRecord::Base
86
+ belongs_to :question, :counter_cache => true, :touch => true
87
+ end
88
+ EOF
89
+ @runner.prepare('app/models/answer.rb', content)
90
+ content = <<-EOF
91
+ class CommentsController < ApplicationController
92
+ def comment_url
93
+ question_path(@answer.question)
94
+ end
95
+ end
96
+ EOF
97
+ @runner.review('app/controllers/comments_controller.rb', content)
98
+ errors = @runner.errors
99
+ errors.should be_empty
100
+ end
101
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsBestPractices::Checks::MoveCodeIntoControllerCheck do
4
+ before(:each) do
5
+ @runner = RailsBestPractices::Core::Runner.new(RailsBestPractices::Checks::MoveCodeIntoControllerCheck.new)
6
+ end
7
+
8
+ it "should move code into controller" do
9
+ content = <<-EOF
10
+ <% @posts = Post.find(:all) %>
11
+ <% @posts.each do |post| %>
12
+ <%=h post.title %>
13
+ <%=h post.content %>
14
+ <% end %>
15
+ EOF
16
+ @runner.review('app/views/posts/index.html.erb', content)
17
+ errors = @runner.errors
18
+ errors.should_not be_empty
19
+ errors[0].to_s.should == "app/views/posts/index.html.erb:1 - move code into controller"
20
+ end
21
+
22
+ it "should not move code into controller" do
23
+ content = <<-EOF
24
+ <% @posts.each do |post| %>
25
+ <%=h post.title %>
26
+ <%=h post.content %>
27
+ <% end %>
28
+ EOF
29
+ @runner.review('app/views/posts/index.html.erb', content)
30
+ errors = @runner.errors
31
+ errors.should be_empty
32
+ end
33
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsBestPractices::Checks::MoveCodeIntoHelperCheck do
4
+ before(:each) do
5
+ @runner = RailsBestPractices::Core::Runner.new(RailsBestPractices::Checks::MoveCodeIntoHelperCheck.new('array_count' => 2))
6
+ end
7
+
8
+ it "should move code into helper" do
9
+ content = <<-EOF
10
+ <%= select_tag :state, options_for_select( [[t(:draft), "draft"],
11
+ [t(:published), "published"]],
12
+ params[:default_state] ) %>
13
+ EOF
14
+ @runner.review('app/views/posts/show.html.erb', content)
15
+ errors = @runner.errors
16
+ errors.should_not be_empty
17
+ errors[0].to_s.should == "app/views/posts/show.html.erb:3 - move code into helper (array_count >= 2)"
18
+ end
19
+
20
+ it "should not move code into helper with simple arguments" do
21
+ content = <<-EOF
22
+ <%= select_tag :state, options_for_select( Post.STATES ) %>
23
+ EOF
24
+ @runner.review('app/views/posts/show.html.erb', content)
25
+ errors = @runner.errors
26
+ errors.should be_empty
27
+ end
28
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsBestPractices::Checks::MoveCodeIntoModelCheck do
4
+ before(:each) do
5
+ @runner = RailsBestPractices::Core::Runner.new(RailsBestPractices::Checks::MoveCodeIntoModelCheck.new)
6
+ end
7
+
8
+ it "should move code into model" do
9
+ content =<<-EOF
10
+ <% if current_user && (current_user == @post.user || @post.editors.include?(current_user)) %>
11
+ <%= link_to 'Edit this post', edit_post_url(@post) %>
12
+ <% end %>
13
+ EOF
14
+ @runner.review('app/views/posts/show.html.erb', content)
15
+ errors = @runner.errors
16
+ errors.should_not be_empty
17
+ errors[0].to_s.should == "app/views/posts/show.html.erb:1 - move code into model (@post use_count > 2)"
18
+ end
19
+
20
+ it "should move code into model with haml" do
21
+ content =<<-EOF
22
+ - if current_user && (current_user == @post.user || @post.editors.include?(current_user))
23
+ = link_to 'Edit this post', edit_post_url(@post)
24
+ EOF
25
+ @runner.review('app/views/posts/show.html.haml', content)
26
+ errors = @runner.errors
27
+ errors.should_not be_empty
28
+ errors[0].to_s.should == "app/views/posts/show.html.haml:1 - move code into model (@post use_count > 2)"
29
+ end
30
+
31
+ it "should move code into model only review for current if conditional statement" do
32
+ content =<<-EOF
33
+ <% if @post.title %>
34
+ <% if @post.user %>
35
+ <% if @post.description %>
36
+ <% end %>
37
+ <% end %>
38
+ <% end %>
39
+ EOF
40
+ @runner.review('app/views/posts/show.html.erb', content)
41
+ errors = @runner.errors
42
+ errors.should be_empty
43
+ end
44
+
45
+ it "should not move code into model" do
46
+ content =<<-EOF
47
+ <% if @post.editable_by?(current_user) %>
48
+ <%= link_to 'Edit this post', edit_post_url(@post) %>
49
+ <% end %>
50
+ EOF
51
+ @runner.review('app/views/posts/show.html.erb', content)
52
+ errors = @runner.errors
53
+ errors.should be_empty
54
+ end
55
+ end
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsBestPractices::Checks::MoveFinderToNamedScopeCheck do
4
+ before(:each) do
5
+ @runner = RailsBestPractices::Core::Runner.new(RailsBestPractices::Checks::MoveFinderToNamedScopeCheck.new)
6
+ end
7
+
8
+ it "should move finder to named_scope" do
9
+ content = <<-EOF
10
+ class PostsController < ActionController::Base
11
+
12
+ def index
13
+ @public_posts = Post.find(:all, :conditions => { :state => 'public' },
14
+ :limit => 10,
15
+ :order => 'created_at desc')
16
+
17
+ @draft_posts = Post.find(:all, :conditions => { :state => 'draft' },
18
+ :limit => 10,
19
+ :order => 'created_at desc')
20
+ end
21
+ end
22
+ EOF
23
+ @runner.review('app/controllers/posts_controller.rb', content)
24
+ errors = @runner.errors
25
+ errors.size.should == 2
26
+ errors[0].to_s.should == "app/controllers/posts_controller.rb:4 - move finder to named_scope"
27
+ errors[1].to_s.should == "app/controllers/posts_controller.rb:8 - move finder to named_scope"
28
+ end
29
+
30
+ it "should not move simple finder" do
31
+ content = <<-EOF
32
+ class PostsController < ActionController::Base
33
+
34
+ def index
35
+ @all_posts = Post.find(:all)
36
+ @another_all_posts = Post.all
37
+ @first_post = Post.find(:first)
38
+ @another_first_post = Post.first
39
+ @last_post = Post.find(:last)
40
+ @another_last_post = Post.last
41
+ end
42
+ end
43
+ EOF
44
+ @runner.review('app/controllers/posts_controller.rb', content)
45
+ @runner.errors.should be_empty
46
+ end
47
+
48
+ it "should not move namd_scope" do
49
+ content = <<-EOF
50
+ class PostsController < ActionController::Base
51
+
52
+ def index
53
+ @public_posts = Post.published
54
+ @draft_posts = Post.draft
55
+ end
56
+ end
57
+ EOF
58
+ @runner.review('app/controllers/posts_controller.rb', content)
59
+ @runner.errors.should be_empty
60
+ end
61
+
62
+ it "should not review model file" do
63
+ content = <<-EOF
64
+ class Post < ActiveRecord::Base
65
+
66
+ def published
67
+ Post.find(:all, :conditions => { :state => 'public' },
68
+ :limit => 10, :order => 'created_at desc')
69
+ end
70
+
71
+ def published
72
+ Post.find(:all, :conditions => { :state => 'draft' },
73
+ :limit => 10, :order => 'created_at desc')
74
+ end
75
+
76
+ end
77
+ EOF
78
+ @runner.review('app/model/post.rb', content)
79
+ @runner.errors.should be_empty
80
+
81
+ end
82
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsBestPractices::Checks::MoveModelLogicIntoModelCheck do
4
+ before(:each) do
5
+ @runner = RailsBestPractices::Core::Runner.new(RailsBestPractices::Checks::MoveModelLogicIntoModelCheck.new)
6
+ end
7
+
8
+ it "should move model logic into model" do
9
+ content = <<-EOF
10
+ class PostsController < ApplicationController
11
+
12
+ def publish
13
+ @post = Post.find(params[:id])
14
+ @post.update_attributes(:is_published, true)
15
+ @post.approved_by = current_user
16
+ if @post.created_at > Time.now - 7.days
17
+ @post.popular = 100
18
+ else
19
+ @post.popular = 0
20
+ end
21
+ end
22
+
23
+ redirect_to post_url(@post)
24
+ end
25
+ EOF
26
+ @runner.review('app/controllers/posts_controller.rb', content)
27
+ errors = @runner.errors
28
+ errors.should_not be_empty
29
+ errors[0].to_s.should == "app/controllers/posts_controller.rb:3 - move model logic into model (@post use_count > 4)"
30
+ end
31
+
32
+ it "should not move model logic into model with simple model calling" do
33
+ content = <<-EOF
34
+ class PostsController < ApplicationController
35
+
36
+ def publish
37
+ @post = Post.find(params[:id])
38
+ @post.update_attributes(:is_published, true)
39
+ @post.approved_by = current_user
40
+ end
41
+
42
+ redirect_to post_url(@post)
43
+ end
44
+ EOF
45
+ @runner.review('app/controllers/posts_controller.rb', content)
46
+ errors = @runner.errors
47
+ errors.should be_empty
48
+ end
49
+ end