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,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