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.
- data/.gitignore +12 -0
- data/.rspec.example +2 -0
- data/.rvmrc.example +2 -0
- data/.watchr +65 -0
- data/.watchr.example +65 -0
- data/Gemfile +3 -0
- data/README.md +6 -0
- data/Rakefile +45 -0
- data/assets/result.html.haml +53 -0
- data/lib/rails_best_practices.rb +30 -11
- data/lib/rails_best_practices/checks/check.rb +10 -10
- data/lib/rails_best_practices/command.rb +9 -0
- data/lib/rails_best_practices/core/visitable_sexp.rb +9 -10
- data/lib/rails_best_practices/version.rb +1 -1
- data/rails_best_practices.gemspec +32 -0
- data/rubies_test.sh +10 -0
- data/spec/rails_best_practices/checks/add_model_virtual_attribute_check_spec.rb +113 -0
- data/spec/rails_best_practices/checks/always_add_db_index_check_spec.rb +172 -0
- data/spec/rails_best_practices/checks/check_spec.rb +57 -0
- data/spec/rails_best_practices/checks/dry_bundler_in_capistrano_check_spec.rb +39 -0
- data/spec/rails_best_practices/checks/isolate_seed_data_check_spec.rb +105 -0
- data/spec/rails_best_practices/checks/keep_finders_on_their_own_model_check_spec.rb +103 -0
- data/spec/rails_best_practices/checks/law_of_demeter_check_spec.rb +101 -0
- data/spec/rails_best_practices/checks/move_code_into_controller_check_spec.rb +33 -0
- data/spec/rails_best_practices/checks/move_code_into_helper_check_spec.rb +28 -0
- data/spec/rails_best_practices/checks/move_code_into_model_check_spec.rb +55 -0
- data/spec/rails_best_practices/checks/move_finder_to_named_scope_check_spec.rb +82 -0
- data/spec/rails_best_practices/checks/move_model_logic_into_model_check_spec.rb +49 -0
- data/spec/rails_best_practices/checks/needless_deep_nesting_check_spec.rb +140 -0
- data/spec/rails_best_practices/checks/not_use_default_route_check_spec.rb +63 -0
- data/spec/rails_best_practices/checks/overuse_route_customizations_check_spec.rb +159 -0
- data/spec/rails_best_practices/checks/replace_complex_creation_with_factory_method_check_spec.rb +76 -0
- data/spec/rails_best_practices/checks/replace_instance_variable_with_local_variable_check_spec.rb +36 -0
- data/spec/rails_best_practices/checks/use_before_filter_check_spec.rb +85 -0
- data/spec/rails_best_practices/checks/use_model_association_check_spec.rb +71 -0
- data/spec/rails_best_practices/checks/use_observer_check_spec.rb +155 -0
- data/spec/rails_best_practices/checks/use_query_attribute_check_spec.rb +192 -0
- data/spec/rails_best_practices/checks/use_say_with_time_in_migrations_check_spec.rb +113 -0
- data/spec/rails_best_practices/checks/use_scope_access_check_spec.rb +193 -0
- data/spec/rails_best_practices/core/error_spec.rb +7 -0
- data/spec/rails_best_practices/core/visitable_sexp_spec.rb +259 -0
- data/spec/rails_best_practices/core_ext/enumerable_spec.rb +7 -0
- data/spec/rails_best_practices/core_ext/nil_class_spec.rb +11 -0
- data/spec/rails_best_practices_spec.rb +44 -0
- data/spec/spec_helper.rb +4 -0
- 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
|