rails_best_practices 0.6.1 → 0.6.5

Sign up to get free protection for your applications and to get access to all the features.
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,85 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsBestPractices::Checks::UseBeforeFilterCheck do
4
+ before(:each) do
5
+ @runner = RailsBestPractices::Core::Runner.new(RailsBestPractices::Checks::UseBeforeFilterCheck.new)
6
+ end
7
+
8
+ it "should use before_filter" do
9
+ content = <<-EOF
10
+ class PostsController < ApplicationController
11
+
12
+ def show
13
+ @post = current_user.posts.find(params[:id])
14
+ end
15
+
16
+ def edit
17
+ @post = current_user.posts.find(params[:id])
18
+ end
19
+
20
+ def update
21
+ @post = current_user.posts.find(params[:id])
22
+ @post.update_attributes(params[:post])
23
+ end
24
+
25
+ def destroy
26
+ @post = current_user.posts.find(params[:id])
27
+ @post.destroy
28
+ end
29
+
30
+ end
31
+ EOF
32
+ @runner.review('app/controllers/posts_controller.rb', content)
33
+ errors = @runner.errors
34
+ errors.should_not be_empty
35
+ errors[0].to_s.should == "app/controllers/posts_controller.rb:3,7,11,16 - use before_filter for show,edit,update,destroy"
36
+ end
37
+
38
+ it "should not use before_filter" do
39
+ content = <<-EOF
40
+ class PostsController < ApplicationController
41
+ before_filter :find_post, :only => [:show, :edit, :update, :destroy]
42
+
43
+ def update
44
+ @post.update_attributes(params[:post])
45
+ end
46
+
47
+ def destroy
48
+ @post.destroy
49
+ end
50
+
51
+ protected
52
+
53
+ def find_post
54
+ @post = current_user.posts.find(params[:id])
55
+ end
56
+ end
57
+ EOF
58
+ @runner.review('app/controllers/posts_controller.rb', content)
59
+ errors = @runner.errors
60
+ errors.should be_empty
61
+ end
62
+
63
+ it "should not use before_filter by nil" do
64
+ content = <<-EOF
65
+ class PostsController < ApplicationController
66
+
67
+ def show
68
+ end
69
+
70
+ def edit
71
+ end
72
+
73
+ def update
74
+ end
75
+
76
+ def destroy
77
+ end
78
+
79
+ end
80
+ EOF
81
+ @runner.review('app/controllers/posts_controller.rb', content)
82
+ errors = @runner.errors
83
+ errors.should be_empty
84
+ end
85
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsBestPractices::Checks::UseModelAssociationCheck do
4
+ before(:each) do
5
+ @runner = RailsBestPractices::Core::Runner.new(RailsBestPractices::Checks::UseModelAssociationCheck.new)
6
+ end
7
+
8
+ it "should use model association for instance variable" do
9
+ content = <<-EOF
10
+ class PostsController < ApplicationController
11
+
12
+ def create
13
+ @post = Post.new(params[:post])
14
+ @post.user_id = current_user.id
15
+ @post.save
16
+ end
17
+ end
18
+ EOF
19
+ @runner.review('app/controllers/posts_controller.rb', content)
20
+ errors = @runner.errors
21
+ errors.should_not be_empty
22
+ errors[0].to_s.should == "app/controllers/posts_controller.rb:3 - use model association (for @post)"
23
+ end
24
+
25
+ it "should not use model association without association assign" do
26
+ content = <<-EOF
27
+ class PostsController < ApplicationController
28
+
29
+ def create
30
+ @post = Post.new(params[:post])
31
+ @post.save
32
+ end
33
+ end
34
+ EOF
35
+ @runner.review('app/controllers/posts_controller.rb', content)
36
+ errors = @runner.errors
37
+ errors.should be_empty
38
+ end
39
+
40
+ it "should use model association for local variable" do
41
+ content = <<-EOF
42
+ class PostsController < ApplicationController
43
+
44
+ def create
45
+ post = Post.new(params[:post])
46
+ post.user_id = current_user.id
47
+ post.save
48
+ end
49
+ end
50
+ EOF
51
+ @runner.review('app/controllers/posts_controller.rb', content)
52
+ errors = @runner.errors
53
+ errors.should_not be_empty
54
+ errors[0].to_s.should == "app/controllers/posts_controller.rb:3 - use model association (for post)"
55
+ end
56
+
57
+ it "should not use model association" do
58
+ content = <<-EOF
59
+ class PostsController < ApplicationController
60
+
61
+ def create
62
+ post = current_user.posts.buid(params[:post])
63
+ post.save
64
+ end
65
+ end
66
+ EOF
67
+ @runner.review('app/controllers/posts_controller.rb', content)
68
+ errors = @runner.errors
69
+ errors.should be_empty
70
+ end
71
+ end
@@ -0,0 +1,155 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsBestPractices::Checks::UseObserverCheck do
4
+ before(:each) do
5
+ @runner = RailsBestPractices::Core::Runner.new(RailsBestPractices::Checks::UseObserverCheck.new)
6
+
7
+ content =<<-EOF
8
+ class ProjectMailer < ActionMailer::Base
9
+ end
10
+ EOF
11
+ @runner.prepare('app/models/project_mailer.rb', content)
12
+ end
13
+
14
+ describe "rails2" do
15
+ it "should use observer" do
16
+ content =<<-EOF
17
+ class Project < ActiveRecord::Base
18
+ after_create :send_create_notification
19
+
20
+ private
21
+
22
+ def send_create_notification
23
+ self.members.each do |member|
24
+ ProjectMailer.deliver_notification(self, member)
25
+ end
26
+ end
27
+ end
28
+ EOF
29
+ @runner.review('app/models/project.rb', content)
30
+ errors = @runner.errors
31
+ errors.should_not be_empty
32
+ errors[0].to_s.should == "app/models/project.rb:6 - use observer"
33
+ end
34
+
35
+ it "should not use observer without callback" do
36
+ content =<<-EOF
37
+ class Project < ActiveRecord::Base
38
+ private
39
+
40
+ def send_create_notification
41
+ self.members.each do |member|
42
+ ProjectMailer.deliver_notification(self, member)
43
+ end
44
+ end
45
+ end
46
+ EOF
47
+ @runner.review('app/models/project.rb', content)
48
+ errors = @runner.errors
49
+ errors.should be_empty
50
+ end
51
+
52
+ it "should use observer with two after_create" do
53
+ content =<<-EOF
54
+ class Project < ActiveRecord::Base
55
+ after_create :send_create_notification, :update_author
56
+
57
+ private
58
+
59
+ def send_create_notification
60
+ self.members.each do |member|
61
+ ProjectMailer.deliver_notification(self, member)
62
+ end
63
+ end
64
+
65
+ def update_author
66
+ end
67
+ end
68
+ EOF
69
+ @runner.review('app/models/project.rb', content)
70
+ errors = @runner.errors
71
+ errors.should_not be_empty
72
+ errors[0].to_s.should == "app/models/project.rb:6 - use observer"
73
+ end
74
+
75
+ it "should not raise when initiate an object in callback" do
76
+ content =<<-EOF
77
+ class Project < ActiveRecord::Base
78
+ after_create ProjectMailer.new
79
+ end
80
+ EOF
81
+ lambda { @runner.review('app/models/project.rb', content) }.should_not raise_error
82
+ end
83
+ end
84
+
85
+ describe "rails3" do
86
+ it "should use observer" do
87
+ content =<<-EOF
88
+ class Project < ActiveRecord::Base
89
+ after_create :send_create_notification
90
+
91
+ private
92
+
93
+ def send_create_notification
94
+ self.members.each do |member|
95
+ ProjectMailer.notification(self, member).deliver
96
+ end
97
+ end
98
+ end
99
+ EOF
100
+ @runner.review('app/models/project.rb', content)
101
+ errors = @runner.errors
102
+ errors.should_not be_empty
103
+ errors[0].to_s.should == "app/models/project.rb:6 - use observer"
104
+ end
105
+
106
+ it "should not use observer without callback" do
107
+ content =<<-EOF
108
+ class Project < ActiveRecord::Base
109
+ private
110
+
111
+ def send_create_notification
112
+ self.members.each do |member|
113
+ ProjectMailer.notification(self, member).deliver
114
+ end
115
+ end
116
+ end
117
+ EOF
118
+ @runner.review('app/models/project.rb', content)
119
+ errors = @runner.errors
120
+ errors.should be_empty
121
+ end
122
+
123
+ it "should use observer with two after_create" do
124
+ content =<<-EOF
125
+ class Project < ActiveRecord::Base
126
+ after_create :send_create_notification, :update_author
127
+
128
+ private
129
+
130
+ def send_create_notification
131
+ self.members.each do |member|
132
+ ProjectMailer.notification(self, member).deliver
133
+ end
134
+ end
135
+
136
+ def update_author
137
+ end
138
+ end
139
+ EOF
140
+ @runner.review('app/models/project.rb', content)
141
+ errors = @runner.errors
142
+ errors.should_not be_empty
143
+ errors[0].to_s.should == "app/models/project.rb:6 - use observer"
144
+ end
145
+
146
+ it "should not raise when initiate an object in callback" do
147
+ content =<<-EOF
148
+ class Project < ActiveRecord::Base
149
+ after_create ProjectMailer.new
150
+ end
151
+ EOF
152
+ lambda { @runner.review('app/models/project.rb', content) }.should_not raise_error
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,192 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsBestPractices::Checks::UseQueryAttributeCheck do
4
+
5
+ before(:each) do
6
+ @runner = RailsBestPractices::Core::Runner.new(RailsBestPractices::Checks::UseQueryAttributeCheck.new)
7
+
8
+ content = <<-EOF
9
+ class User < ActiveRecord::Base
10
+ has_many :projects
11
+ belongs_to :location
12
+ has_one :phone
13
+
14
+ belongs_to :category, :class_name => 'IssueCategory', :foreign_key => 'category_id'
15
+ end
16
+ EOF
17
+ @runner.prepare('app/models/user.rb', content)
18
+ end
19
+
20
+ it "should use query attribute by blank call" do
21
+ content = <<-EOF
22
+ <% if @user.login.blank? %>
23
+ <%= link_to 'login', new_session_path %>
24
+ <% end %>
25
+ EOF
26
+ @runner.review('app/views/users/show.html.erb', content)
27
+ errors = @runner.errors
28
+ errors.should_not be_empty
29
+ errors[0].to_s.should == "app/views/users/show.html.erb:1 - use query attribute (@user.login?)"
30
+ end
31
+
32
+ it "should use query attribute by comparing empty string" do
33
+ content = <<-EOF
34
+ <% if @user.login == "" %>
35
+ <%= link_to 'login', new_session_path %>
36
+ <% end %>
37
+ EOF
38
+ @runner.review('app/views/users/show.html.erb', content)
39
+ errors = @runner.errors
40
+ errors.should_not be_empty
41
+ errors[0].to_s.should == "app/views/users/show.html.erb:1 - use query attribute (@user.login?)"
42
+ end
43
+
44
+ it "should use query attribute by nil call" do
45
+ content = <<-EOF
46
+ <% if @user.login.nil? %>
47
+ <%= link_to 'login', new_session_path %>
48
+ <% end %>
49
+ EOF
50
+ @runner.review('app/views/users/show.html.erb', content)
51
+ errors = @runner.errors
52
+ errors.should_not be_empty
53
+ errors[0].to_s.should == "app/views/users/show.html.erb:1 - use query attribute (@user.login?)"
54
+ end
55
+
56
+ it "should use query attribute by present call" do
57
+ content = <<-EOF
58
+ <% if @user.login.present? %>
59
+ <%= @user.login %>
60
+ <% end %>
61
+ EOF
62
+ @runner.review('app/views/users/show.html.erb', content)
63
+ errors = @runner.errors
64
+ errors.should_not be_empty
65
+ errors[0].to_s.should == "app/views/users/show.html.erb:1 - use query attribute (@user.login?)"
66
+ end
67
+
68
+ it "should use query attribute within and conditions" do
69
+ content = <<-EOF
70
+ <% if @user.active? and @user.login.present? %>
71
+ <%= @user.login %>
72
+ <% end %>
73
+ EOF
74
+ @runner.review('app/views/users/show.html.erb', content)
75
+ errors = @runner.errors
76
+ errors.should_not be_empty
77
+ errors[0].to_s.should == "app/views/users/show.html.erb:1 - use query attribute (@user.login?)"
78
+ end
79
+
80
+ it "should use query attribute within or conditions" do
81
+ content = <<-EOF
82
+ <% if @user.active? or @user.login != "" %>
83
+ <%= @user.login %>
84
+ <% end %>
85
+ EOF
86
+ @runner.review('app/views/users/show.html.erb', content)
87
+ errors = @runner.errors
88
+ errors.should_not be_empty
89
+ errors[0].to_s.should == "app/views/users/show.html.erb:1 - use query attribute (@user.login?)"
90
+ end
91
+
92
+ it "should not use query attribute" do
93
+ content = <<-EOF
94
+ <% if @user.login? %>
95
+ <%= @user.login %>
96
+ <% end %>
97
+ EOF
98
+ @runner.review('app/views/users/show.html.erb', content)
99
+ errors = @runner.errors
100
+ errors.should be_empty
101
+ end
102
+
103
+ it "should not review for pluralize attribute" do
104
+ content = <<-EOF
105
+ <% if @user.roles.blank? %>
106
+ <%= @user.login %>
107
+ <% end %>
108
+ EOF
109
+ @runner.review('app/views/users/show.html.erb', content)
110
+ errors = @runner.errors
111
+ errors.should be_empty
112
+ end
113
+
114
+ it "should not review non model class" do
115
+ content = <<-EOF
116
+ <% if @person.login.present? %>
117
+ <%= @person.login %>
118
+ <% end %>
119
+ EOF
120
+ @runner.review('app/views/users/show.html.erb', content)
121
+ errors = @runner.errors
122
+ errors.should be_empty
123
+ end
124
+
125
+ context "association" do
126
+ it "should not review belongs_to association" do
127
+ content = <<-EOF
128
+ <% if @user.location.present? %>
129
+ <%= @user.location.name %>
130
+ <% end %>
131
+ EOF
132
+ @runner.review('app/views/users/show.html.erb', content)
133
+ errors = @runner.errors
134
+ errors.should be_empty
135
+ end
136
+
137
+ it "should not review belongs_to category" do
138
+ content = <<-EOF
139
+ <% if @user.category.present? %>
140
+ <%= @user.category.name %>
141
+ <% end %>
142
+ EOF
143
+ @runner.review('app/views/users/show.html.erb', content)
144
+ errors = @runner.errors
145
+ errors.should be_empty
146
+ end
147
+
148
+ it "should not review has_one association" do
149
+ content = <<-EOF
150
+ <% if @user.phone.present? %>
151
+ <%= @user.phone.number %>
152
+ <% end %>
153
+ EOF
154
+ @runner.review('app/views/users/show.html.erb', content)
155
+ errors = @runner.errors
156
+ errors.should be_empty
157
+ end
158
+
159
+ it "should not review has_many association" do
160
+ content = <<-EOF
161
+ <% if @user.projects.present? %>
162
+ <%= @user.projects.first.name %>
163
+ <% end %>
164
+ EOF
165
+ @runner.review('app/views/users/show.html.erb', content)
166
+ errors = @runner.errors
167
+ errors.should be_empty
168
+ end
169
+ end
170
+
171
+ it "should not review for class method" do
172
+ content = <<-EOF
173
+ <% if User.name.present? %>
174
+ <%= User.name %>
175
+ <% end %>
176
+ EOF
177
+ @runner.review('app/views/users/show.html.erb', content)
178
+ errors = @runner.errors
179
+ errors.should be_empty
180
+ end
181
+
182
+ it "should not review for non attribute call" do
183
+ content = <<-EOF
184
+ if @user.login(false).nil?
185
+ puts @user.login(false)
186
+ end
187
+ EOF
188
+ @runner.review('app/models/users_controller.rb', content)
189
+ errors = @runner.errors
190
+ errors.should be_empty
191
+ end
192
+ end