rails_best_practices 0.10.1 → 1.0.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.
- data/README.md +20 -0
- data/assets/result.html.haml +1 -1
- data/lib/rails_best_practices.rb +5 -3
- data/lib/rails_best_practices/core.rb +1 -1
- data/lib/rails_best_practices/core/check.rb +9 -12
- data/lib/rails_best_practices/core/checking_visitor.rb +9 -6
- data/lib/rails_best_practices/core/model_associations.rb +1 -1
- data/lib/rails_best_practices/core/nil.rb +5 -1
- data/lib/rails_best_practices/core/runner.rb +5 -5
- data/lib/rails_best_practices/core_ext/sexp.rb +688 -0
- data/lib/rails_best_practices/prepares/mailer_prepare.rb +4 -5
- data/lib/rails_best_practices/prepares/model_prepare.rb +16 -26
- data/lib/rails_best_practices/prepares/schema_prepare.rb +11 -17
- data/lib/rails_best_practices/reviews/add_model_virtual_attribute_review.rb +24 -75
- data/lib/rails_best_practices/reviews/always_add_db_index_review.rb +39 -113
- data/lib/rails_best_practices/reviews/dry_bundler_in_capistrano_review.rb +6 -16
- data/lib/rails_best_practices/reviews/isolate_seed_data_review.rb +16 -32
- data/lib/rails_best_practices/reviews/keep_finders_on_their_own_model_review.rb +11 -20
- data/lib/rails_best_practices/reviews/law_of_demeter_review.rb +7 -28
- data/lib/rails_best_practices/reviews/move_code_into_controller_review.rb +16 -14
- data/lib/rails_best_practices/reviews/move_code_into_helper_review.rb +10 -28
- data/lib/rails_best_practices/reviews/move_code_into_model_review.rb +12 -11
- data/lib/rails_best_practices/reviews/move_finder_to_named_scope_review.rb +13 -24
- data/lib/rails_best_practices/reviews/move_model_logic_into_model_review.rb +9 -9
- data/lib/rails_best_practices/reviews/needless_deep_nesting_review.rb +24 -68
- data/lib/rails_best_practices/reviews/not_use_default_route_review.rb +15 -22
- data/lib/rails_best_practices/reviews/overuse_route_customizations_review.rb +31 -91
- data/lib/rails_best_practices/reviews/remove_empty_helpers_review.rb +4 -2
- data/lib/rails_best_practices/reviews/replace_complex_creation_with_factory_method_review.rb +20 -18
- data/lib/rails_best_practices/reviews/replace_instance_variable_with_local_variable_review.rb +5 -3
- data/lib/rails_best_practices/reviews/review.rb +8 -37
- data/lib/rails_best_practices/reviews/simplify_render_in_controllers_review.rb +10 -6
- data/lib/rails_best_practices/reviews/simplify_render_in_views_review.rb +9 -6
- data/lib/rails_best_practices/reviews/use_before_filter_review.rb +14 -72
- data/lib/rails_best_practices/reviews/use_model_association_review.rb +19 -31
- data/lib/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review.rb +5 -5
- data/lib/rails_best_practices/reviews/use_observer_review.rb +22 -40
- data/lib/rails_best_practices/reviews/use_query_attribute_review.rb +34 -39
- data/lib/rails_best_practices/reviews/use_say_with_time_in_migrations_review.rb +14 -38
- data/lib/rails_best_practices/reviews/use_scope_access_review.rb +13 -44
- data/lib/rails_best_practices/version.rb +1 -1
- data/spec/rails_best_practices/core/check_spec.rb +5 -5
- data/spec/rails_best_practices/core/checking_visitor_spec.rb +4 -4
- data/spec/rails_best_practices/core/model_associations_spec.rb +4 -4
- data/spec/rails_best_practices/core/nil_spec.rb +7 -1
- data/spec/rails_best_practices/core_ext/sexp_spec.rb +430 -0
- data/spec/rails_best_practices/prepares/model_prepare_spec.rb +12 -12
- data/spec/rails_best_practices/prepares/schema_prepare_spec.rb +6 -6
- data/spec/rails_best_practices/reviews/move_code_into_controller_review_spec.rb +14 -2
- data/spec/rails_best_practices/reviews/move_code_into_helper_review_spec.rb +1 -1
- data/spec/rails_best_practices/reviews/needless_deep_nesting_review_spec.rb +3 -3
- data/spec/rails_best_practices/reviews/not_use_default_route_review_spec.rb +1 -1
- data/spec/rails_best_practices/reviews/overuse_route_customizations_review_spec.rb +15 -1
- data/spec/rails_best_practices/reviews/simplify_render_in_controllers_review_spec.rb +3 -3
- data/spec/rails_best_practices/reviews/use_query_attribute_review_spec.rb +1 -1
- data/spec/rails_best_practices/reviews/use_say_with_time_in_migrations_review_spec.rb +1 -1
- data/spec/rails_best_practices/reviews/use_scope_access_review_spec.rb +4 -4
- data/spec/rails_best_practices_spec.rb +1 -3
- data/spec/spec_helper.rb +4 -0
- metadata +6 -8
- data/lib/rails_best_practices/core/visitable_sexp.rb +0 -444
- data/spec/rails_best_practices/core/visitable_sexp_spec.rb +0 -272
- data/spec/rails_best_practices/reviews/review_spec.rb +0 -11
@@ -18,10 +18,10 @@ describe RailsBestPractices::Prepares::ModelPrepare do
|
|
18
18
|
EOF
|
19
19
|
runner.prepare('app/models/project.rb', content)
|
20
20
|
model_associations = RailsBestPractices::Prepares.model_associations
|
21
|
-
model_associations.get_association("Project", "portfolio").should == {
|
22
|
-
model_associations.get_association("Project", "project_manager").should == {
|
23
|
-
model_associations.get_association("Project", "milestones").should == {
|
24
|
-
model_associations.get_association("Project", "categories").should == {
|
21
|
+
model_associations.get_association("Project", "portfolio").should == {"meta" => "belongs_to", "class_name" => "Portfolio"}
|
22
|
+
model_associations.get_association("Project", "project_manager").should == {"meta" => "has_one", "class_name" => "ProjectManager"}
|
23
|
+
model_associations.get_association("Project", "milestones").should == {"meta" => "has_many", "class_name" => "Milestone"}
|
24
|
+
model_associations.get_association("Project", "categories").should == {"meta" => "has_and_belongs_to_many", "class_name" => "Category"}
|
25
25
|
end
|
26
26
|
|
27
27
|
it "should not raise error for finder_sql option" do
|
@@ -38,45 +38,45 @@ describe RailsBestPractices::Prepares::ModelPrepare do
|
|
38
38
|
it "should parse belongs_to" do
|
39
39
|
content =<<-EOF
|
40
40
|
class Post < ActiveRecord::Base
|
41
|
-
belongs_to :author,
|
41
|
+
belongs_to :author, "class_name" => "Person"
|
42
42
|
end
|
43
43
|
EOF
|
44
44
|
runner.prepare("app/models/post.rb", content)
|
45
45
|
model_associations = RailsBestPractices::Prepares.model_associations
|
46
|
-
model_associations.get_association("Post", "author").should == {
|
46
|
+
model_associations.get_association("Post", "author").should == {"meta" => "belongs_to", "class_name" => "Person"}
|
47
47
|
end
|
48
48
|
|
49
49
|
it "should parse has_one" do
|
50
50
|
content =<<-EOF
|
51
51
|
class Project < ActiveRecord::Base
|
52
|
-
has_one :project_manager,
|
52
|
+
has_one :project_manager, "class_name" => "Person"
|
53
53
|
end
|
54
54
|
EOF
|
55
55
|
runner.prepare("app/models/post.rb", content)
|
56
56
|
model_associations = RailsBestPractices::Prepares.model_associations
|
57
|
-
model_associations.get_association("Project", "project_manager").should == {
|
57
|
+
model_associations.get_association("Project", "project_manager").should == {"meta" => "has_one", "class_name" => "Person"}
|
58
58
|
end
|
59
59
|
|
60
60
|
it "should parse has_many" do
|
61
61
|
content =<<-EOF
|
62
62
|
class Project < ActiveRecord::Base
|
63
|
-
has_many :people,
|
63
|
+
has_many :people, "class_name" => "Person"
|
64
64
|
end
|
65
65
|
EOF
|
66
66
|
runner.prepare("app/models/project.rb", content)
|
67
67
|
model_associations = RailsBestPractices::Prepares.model_associations
|
68
|
-
model_associations.get_association("Project", "people").should == {
|
68
|
+
model_associations.get_association("Project", "people").should == {"meta" => "has_many", "class_name" => "Person"}
|
69
69
|
end
|
70
70
|
|
71
71
|
it "should parse has_and_belongs_to_many" do
|
72
72
|
content =<<-EOF
|
73
73
|
class Citizen < ActiveRecord::Base
|
74
|
-
has_and_belongs_to_many :nations,
|
74
|
+
has_and_belongs_to_many :nations, "class_name" => "Country"
|
75
75
|
end
|
76
76
|
EOF
|
77
77
|
runner.prepare("app/models/citizen.rb", content)
|
78
78
|
model_associations = RailsBestPractices::Prepares.model_associations
|
79
|
-
model_associations.get_association("Citizen", "nations").should == {
|
79
|
+
model_associations.get_association("Citizen", "nations").should == {"meta" => "has_and_belongs_to_many", "class_name" => "Country"}
|
80
80
|
end
|
81
81
|
end
|
82
82
|
end
|
@@ -18,11 +18,11 @@ describe RailsBestPractices::Prepares::SchemaPrepare do
|
|
18
18
|
EOF
|
19
19
|
runner.prepare("db/schema.rb", content)
|
20
20
|
model_attributes = RailsBestPractices::Prepares.model_attributes
|
21
|
-
model_attributes.get_attribute_type("Post", "title").should ==
|
22
|
-
model_attributes.get_attribute_type("Post", "body").should ==
|
23
|
-
model_attributes.get_attribute_type("Post", "created_at").should ==
|
24
|
-
model_attributes.get_attribute_type("Post", "user_id").should ==
|
25
|
-
model_attributes.get_attribute_type("Post", "comments_count").should ==
|
26
|
-
model_attributes.get_attribute_type("Post", "published").should ==
|
21
|
+
model_attributes.get_attribute_type("Post", "title").should == "string"
|
22
|
+
model_attributes.get_attribute_type("Post", "body").should == "text"
|
23
|
+
model_attributes.get_attribute_type("Post", "created_at").should == "datetime"
|
24
|
+
model_attributes.get_attribute_type("Post", "user_id").should == "integer"
|
25
|
+
model_attributes.get_attribute_type("Post", "comments_count").should == "integer"
|
26
|
+
model_attributes.get_attribute_type("Post", "published").should == "boolean"
|
27
27
|
end
|
28
28
|
end
|
@@ -3,9 +3,21 @@ require 'spec_helper'
|
|
3
3
|
describe RailsBestPractices::Reviews::MoveCodeIntoControllerReview do
|
4
4
|
let(:runner) { RailsBestPractices::Core::Runner.new(:reviews => RailsBestPractices::Reviews::MoveCodeIntoControllerReview.new) }
|
5
5
|
|
6
|
-
it "should move code into controller" do
|
6
|
+
it "should move code into controller for method call" do
|
7
7
|
content = <<-EOF
|
8
|
-
<%
|
8
|
+
<% Post.find(:all).each do |post| %>
|
9
|
+
<%=h post.title %>
|
10
|
+
<%=h post.content %>
|
11
|
+
<% end %>
|
12
|
+
EOF
|
13
|
+
runner.review('app/views/posts/index.html.erb', content)
|
14
|
+
runner.should have(1).errors
|
15
|
+
runner.errors[0].to_s.should == "app/views/posts/index.html.erb:1 - move code into controller"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should move code into controller for assign" do
|
19
|
+
content = <<-EOF
|
20
|
+
<% @posts = Post.all %>
|
9
21
|
<% @posts.each do |post| %>
|
10
22
|
<%=h post.title %>
|
11
23
|
<%=h post.content %>
|
@@ -11,7 +11,7 @@ describe RailsBestPractices::Reviews::MoveCodeIntoHelperReview do
|
|
11
11
|
EOF
|
12
12
|
runner.review('app/views/posts/show.html.erb', content)
|
13
13
|
runner.should have(1).errors
|
14
|
-
runner.errors[0].to_s.should == "app/views/posts/show.html.erb:
|
14
|
+
runner.errors[0].to_s.should == "app/views/posts/show.html.erb:1 - move code into helper (array_count >= 2)"
|
15
15
|
end
|
16
16
|
|
17
17
|
it "should not move code into helper with simple arguments" do
|
@@ -93,7 +93,7 @@ describe RailsBestPractices::Reviews::NeedlessDeepNestingReview do
|
|
93
93
|
EOF
|
94
94
|
runner.review('config/routes.rb', content)
|
95
95
|
runner.should have(1).errors
|
96
|
-
runner.errors[0].to_s.should == "config/routes.rb:
|
96
|
+
runner.errors[0].to_s.should == "config/routes.rb:3 - needless deep nesting (nested_count > 2)"
|
97
97
|
end
|
98
98
|
|
99
99
|
it "should not needless deep nesting for shallow" do
|
@@ -118,7 +118,7 @@ describe RailsBestPractices::Reviews::NeedlessDeepNestingReview do
|
|
118
118
|
EOF
|
119
119
|
runner.review('config/routes.rb', content)
|
120
120
|
runner.should have(1).errors
|
121
|
-
runner.errors[0].to_s.should == "config/routes.rb:
|
121
|
+
runner.errors[0].to_s.should == "config/routes.rb:3 - needless deep nesting (nested_count > 2)"
|
122
122
|
end
|
123
123
|
|
124
124
|
it "should needless deep nesting with block node" do
|
@@ -132,7 +132,7 @@ describe RailsBestPractices::Reviews::NeedlessDeepNestingReview do
|
|
132
132
|
EOF
|
133
133
|
runner.review('config/routes.rb', content)
|
134
134
|
runner.should have(1).errors
|
135
|
-
runner.errors[0].to_s.should == "config/routes.rb:
|
135
|
+
runner.errors[0].to_s.should == "config/routes.rb:3 - needless deep nesting (nested_count > 2)"
|
136
136
|
end
|
137
137
|
|
138
138
|
it "should no needless deep nesting" do
|
@@ -41,7 +41,7 @@ describe RailsBestPractices::Reviews::NotUseDefaultRouteReview do
|
|
41
41
|
EOF
|
42
42
|
runner.review('config/routes.rb', content)
|
43
43
|
runner.should have(1).errors
|
44
|
-
runner.errors[0].to_s.should == "config/routes.rb:
|
44
|
+
runner.errors[0].to_s.should == "config/routes.rb:4 - not use default route"
|
45
45
|
end
|
46
46
|
|
47
47
|
it "should no not use default route" do
|
@@ -32,7 +32,7 @@ describe RailsBestPractices::Reviews::OveruseRouteCustomizationsReview do
|
|
32
32
|
runner.errors[0].to_s.should == "config/routes.rb:2 - overuse route customizations (customize_count > 3)"
|
33
33
|
end
|
34
34
|
|
35
|
-
it "should overuse route customizations with collection
|
35
|
+
it "should overuse route customizations with hash member and collection" do
|
36
36
|
content = <<-EOF
|
37
37
|
ActionController::Routing::Routes.draw do |map|
|
38
38
|
map.resources :categories do |category|
|
@@ -48,6 +48,20 @@ describe RailsBestPractices::Reviews::OveruseRouteCustomizationsReview do
|
|
48
48
|
runner.errors[0].to_s.should == "config/routes.rb:3 - overuse route customizations (customize_count > 3)"
|
49
49
|
end
|
50
50
|
|
51
|
+
it "should overuse route customizations with array member and collection" do
|
52
|
+
content = <<-EOF
|
53
|
+
ActionController::Routing::Routes.draw do |map|
|
54
|
+
map.resources :categories do |category|
|
55
|
+
category.resources :posts, :member => [:create_comment, :update_comment, :delete_comment],
|
56
|
+
:collection => [:comments]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
EOF
|
60
|
+
runner.review('config/routes.rb', content)
|
61
|
+
runner.should have(1).errors
|
62
|
+
runner.errors[0].to_s.should == "config/routes.rb:3 - overuse route customizations (customize_count > 3)"
|
63
|
+
end
|
64
|
+
|
51
65
|
it "should not overuse route customizations without customization" do
|
52
66
|
content = <<-EOF
|
53
67
|
ActionController::Routing::Routes.draw do |map|
|
@@ -11,7 +11,7 @@ describe RailsBestPractices::Reviews::SimplifyRenderInControllersReview do
|
|
11
11
|
EOF
|
12
12
|
runner.review("app/controllers/posts_controller.rb", content)
|
13
13
|
runner.should have(1).errors
|
14
|
-
runner.errors[0].to_s.should == "app/controllers/posts_controller.rb:
|
14
|
+
runner.errors[0].to_s.should == "app/controllers/posts_controller.rb:2 - simplify render in controllers"
|
15
15
|
end
|
16
16
|
|
17
17
|
it "should simplify render actions's template" do
|
@@ -22,7 +22,7 @@ describe RailsBestPractices::Reviews::SimplifyRenderInControllersReview do
|
|
22
22
|
EOF
|
23
23
|
runner.review("app/controllers/posts_controller.rb", content)
|
24
24
|
runner.should have(1).errors
|
25
|
-
runner.errors[0].to_s.should == "app/controllers/posts_controller.rb:
|
25
|
+
runner.errors[0].to_s.should == "app/controllers/posts_controller.rb:2 - simplify render in controllers"
|
26
26
|
end
|
27
27
|
|
28
28
|
it "should simplify render an arbitrary file" do
|
@@ -33,7 +33,7 @@ describe RailsBestPractices::Reviews::SimplifyRenderInControllersReview do
|
|
33
33
|
EOF
|
34
34
|
runner.review("app/controllers/posts_controller.rb", content)
|
35
35
|
runner.should have(1).errors
|
36
|
-
runner.errors[0].to_s.should == "app/controllers/posts_controller.rb:
|
36
|
+
runner.errors[0].to_s.should == "app/controllers/posts_controller.rb:2 - simplify render in controllers"
|
37
37
|
end
|
38
38
|
|
39
39
|
it "should not simplify render action view" do
|
@@ -77,7 +77,7 @@ describe RailsBestPractices::Reviews::UseQueryAttributeReview do
|
|
77
77
|
|
78
78
|
it "should use query attribute within and conditions" do
|
79
79
|
content = <<-EOF
|
80
|
-
<% if @user.active?
|
80
|
+
<% if @user.active? && @user.login.present? %>
|
81
81
|
<%= @user.login %>
|
82
82
|
<% end %>
|
83
83
|
EOF
|
@@ -20,7 +20,7 @@ describe RailsBestPractices::Reviews::UseScopeAccessReview do
|
|
20
20
|
EOF
|
21
21
|
runner.review('app/controllers/posts_controller.rb', content)
|
22
22
|
runner.should have(1).errors
|
23
|
-
runner.errors[0].to_s.should == "app/controllers/posts_controller.rb:
|
23
|
+
runner.errors[0].to_s.should == "app/controllers/posts_controller.rb:6 - use scope access"
|
24
24
|
end
|
25
25
|
|
26
26
|
it "shoud use scope access by comparing with id" do
|
@@ -39,7 +39,7 @@ describe RailsBestPractices::Reviews::UseScopeAccessReview do
|
|
39
39
|
EOF
|
40
40
|
runner.review('app/controllers/posts_controller.rb', content)
|
41
41
|
runner.should have(1).errors
|
42
|
-
runner.errors[0].to_s.should == "app/controllers/posts_controller.rb:
|
42
|
+
runner.errors[0].to_s.should == "app/controllers/posts_controller.rb:6 - use scope access"
|
43
43
|
end
|
44
44
|
|
45
45
|
it "shoud use scope access with current_user ==" do
|
@@ -58,7 +58,7 @@ describe RailsBestPractices::Reviews::UseScopeAccessReview do
|
|
58
58
|
EOF
|
59
59
|
runner.review('app/controllers/posts_controller.rb', content)
|
60
60
|
runner.should have(1).errors
|
61
|
-
runner.errors[0].to_s.should == "app/controllers/posts_controller.rb:
|
61
|
+
runner.errors[0].to_s.should == "app/controllers/posts_controller.rb:6 - use scope access"
|
62
62
|
end
|
63
63
|
|
64
64
|
it "shoud use scope access by current_user.id ==" do
|
@@ -77,7 +77,7 @@ describe RailsBestPractices::Reviews::UseScopeAccessReview do
|
|
77
77
|
EOF
|
78
78
|
runner.review('app/controllers/posts_controller.rb', content)
|
79
79
|
runner.should have(1).errors
|
80
|
-
runner.errors[0].to_s.should == "app/controllers/posts_controller.rb:
|
80
|
+
runner.errors[0].to_s.should == "app/controllers/posts_controller.rb:6 - use scope access"
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
@@ -7,8 +7,6 @@ describe RailsBestPractices do
|
|
7
7
|
it "should expand all files in spec directory" do
|
8
8
|
dir = File.dirname(__FILE__)
|
9
9
|
RailsBestPractices.expand_dirs_to_files(dir).should be_include(dir + '/rails_best_practices_spec.rb')
|
10
|
-
RailsBestPractices.expand_dirs_to_files(dir).should be_include(dir + '/rails_best_practices/core/visitable_sexp_spec.rb')
|
11
|
-
RailsBestPractices.expand_dirs_to_files(dir).should be_include(dir + '/rails_best_practices/reviews/review_spec.rb')
|
12
10
|
end
|
13
11
|
end
|
14
12
|
|
@@ -40,6 +38,6 @@ describe RailsBestPractices do
|
|
40
38
|
RailsBestPractices.output_terminal_errors
|
41
39
|
result = $stdout.string
|
42
40
|
$stdout = $origin_stdout
|
43
|
-
result.should == ["app/models/user.rb:10 - law of demeter".red, "app/models/post.rb:100 - use query attribute".red, "\nPlease go to http://rails-bestpractices.com to see more useful Rails Best Practices.".green, "\nFound 2
|
41
|
+
result.should == ["app/models/user.rb:10 - law of demeter".red, "app/models/post.rb:100 - use query attribute".red, "\nPlease go to http://rails-bestpractices.com to see more useful Rails Best Practices.".green, "\nFound 2 warnings.".red].join("\n") + "\n"
|
44
42
|
end
|
45
43
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: rails_best_practices
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 1.0.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Richard Huang
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-09-24 00:00:00 +08:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -170,8 +170,8 @@ files:
|
|
170
170
|
- lib/rails_best_practices/core/models.rb
|
171
171
|
- lib/rails_best_practices/core/nil.rb
|
172
172
|
- lib/rails_best_practices/core/runner.rb
|
173
|
-
- lib/rails_best_practices/core/visitable_sexp.rb
|
174
173
|
- lib/rails_best_practices/core_ext/enumerable.rb
|
174
|
+
- lib/rails_best_practices/core_ext/sexp.rb
|
175
175
|
- lib/rails_best_practices/lexicals.rb
|
176
176
|
- lib/rails_best_practices/lexicals/remove_tab_check.rb
|
177
177
|
- lib/rails_best_practices/lexicals/remove_trailing_whitespace_check.rb
|
@@ -218,8 +218,8 @@ files:
|
|
218
218
|
- spec/rails_best_practices/core/model_attributes_spec.rb
|
219
219
|
- spec/rails_best_practices/core/models_spec.rb
|
220
220
|
- spec/rails_best_practices/core/nil_spec.rb
|
221
|
-
- spec/rails_best_practices/core/visitable_sexp_spec.rb
|
222
221
|
- spec/rails_best_practices/core_ext/enumerable_spec.rb
|
222
|
+
- spec/rails_best_practices/core_ext/sexp_spec.rb
|
223
223
|
- spec/rails_best_practices/lexicals/remove_tab_check_spec.rb
|
224
224
|
- spec/rails_best_practices/lexicals/remove_trailing_whitespace_check_spec.rb
|
225
225
|
- spec/rails_best_practices/prepares/mailer_prepare_spec.rb
|
@@ -242,7 +242,6 @@ files:
|
|
242
242
|
- spec/rails_best_practices/reviews/remove_empty_helpers_review_spec.rb
|
243
243
|
- spec/rails_best_practices/reviews/replace_complex_creation_with_factory_method_review_spec.rb
|
244
244
|
- spec/rails_best_practices/reviews/replace_instance_variable_with_local_variable_review_spec.rb
|
245
|
-
- spec/rails_best_practices/reviews/review_spec.rb
|
246
245
|
- spec/rails_best_practices/reviews/simplify_render_in_controllers_review_spec.rb
|
247
246
|
- spec/rails_best_practices/reviews/simplify_render_in_views_review_spec.rb
|
248
247
|
- spec/rails_best_practices/reviews/use_before_filter_review_spec.rb
|
@@ -282,7 +281,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
282
281
|
requirements:
|
283
282
|
- - ">="
|
284
283
|
- !ruby/object:Gem::Version
|
285
|
-
hash:
|
284
|
+
hash: 3845996389708993408
|
286
285
|
segments:
|
287
286
|
- 0
|
288
287
|
version: "0"
|
@@ -307,8 +306,8 @@ test_files:
|
|
307
306
|
- spec/rails_best_practices/core/model_attributes_spec.rb
|
308
307
|
- spec/rails_best_practices/core/models_spec.rb
|
309
308
|
- spec/rails_best_practices/core/nil_spec.rb
|
310
|
-
- spec/rails_best_practices/core/visitable_sexp_spec.rb
|
311
309
|
- spec/rails_best_practices/core_ext/enumerable_spec.rb
|
310
|
+
- spec/rails_best_practices/core_ext/sexp_spec.rb
|
312
311
|
- spec/rails_best_practices/lexicals/remove_tab_check_spec.rb
|
313
312
|
- spec/rails_best_practices/lexicals/remove_trailing_whitespace_check_spec.rb
|
314
313
|
- spec/rails_best_practices/prepares/mailer_prepare_spec.rb
|
@@ -331,7 +330,6 @@ test_files:
|
|
331
330
|
- spec/rails_best_practices/reviews/remove_empty_helpers_review_spec.rb
|
332
331
|
- spec/rails_best_practices/reviews/replace_complex_creation_with_factory_method_review_spec.rb
|
333
332
|
- spec/rails_best_practices/reviews/replace_instance_variable_with_local_variable_review_spec.rb
|
334
|
-
- spec/rails_best_practices/reviews/review_spec.rb
|
335
333
|
- spec/rails_best_practices/reviews/simplify_render_in_controllers_review_spec.rb
|
336
334
|
- spec/rails_best_practices/reviews/simplify_render_in_views_review_spec.rb
|
337
335
|
- spec/rails_best_practices/reviews/use_before_filter_review_spec.rb
|
@@ -1,444 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require 'sexp'
|
3
|
-
|
4
|
-
class Sexp
|
5
|
-
# prepare current node.
|
6
|
-
#
|
7
|
-
# @param [RailsBestPractices::Core::CheckingVisitor] visitor the visitor to prepare current node
|
8
|
-
def prepare(visitor)
|
9
|
-
visitor.prepare(self)
|
10
|
-
end
|
11
|
-
|
12
|
-
# prepare current node.
|
13
|
-
#
|
14
|
-
# @param [RailsBestPractices::Core::CheckingVisitor] visitor the visitor to review current node
|
15
|
-
def review(visitor)
|
16
|
-
visitor.review(self)
|
17
|
-
end
|
18
|
-
|
19
|
-
# return child nodes of a sexp node.
|
20
|
-
#
|
21
|
-
# s(:call, nil, :puts,
|
22
|
-
# s(:arglist, s(:str, "hello "), s(:str, "world"))
|
23
|
-
# )
|
24
|
-
# => [s(:arglist, s(:str, "hello "), s(:str, "world"))]
|
25
|
-
#
|
26
|
-
# @return [Array] child nodes.
|
27
|
-
def children
|
28
|
-
find_all { | sexp | Sexp === sexp }
|
29
|
-
end
|
30
|
-
|
31
|
-
# recursively find all child nodes, and yeild each child node.
|
32
|
-
def recursive_children
|
33
|
-
children.each do |child|
|
34
|
-
yield child
|
35
|
-
child.recursive_children { |c| yield c }
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
# grep all the recursive child nodes with conditions, and yield each match node.
|
40
|
-
#
|
41
|
-
# @param [Hash] options grep conditions
|
42
|
-
#
|
43
|
-
# options is the grep conditions, like
|
44
|
-
#
|
45
|
-
# :node_type => :call,
|
46
|
-
# :subject => s(:const, Post),
|
47
|
-
# :message => [:find, :new],
|
48
|
-
# :arguments => s(:arglist)
|
49
|
-
#
|
50
|
-
# the condition key is one of :node_type, :subject, :message or :arguments,
|
51
|
-
# the condition value can be Symbol, Array or Sexp.
|
52
|
-
def grep_nodes(options)
|
53
|
-
node_type = options[:node_type]
|
54
|
-
subject = options[:subject]
|
55
|
-
message = options[:message]
|
56
|
-
arguments = options[:arguments]
|
57
|
-
self.recursive_children do |child|
|
58
|
-
if (!node_type || (node_type.is_a?(Array) ? node_type.include?(child.node_type) : node_type == child.node_type)) &&
|
59
|
-
(!subject || (subject.is_a?(Array) ? subject.include?(child.subject) : subject == child.subject)) &&
|
60
|
-
(!message || (message.is_a?(Array) ? message.include?(child.message) : message == child.message)) &&
|
61
|
-
(!arguments || (arguments.is_?(Array) ? arguments.include?(child.arguments) : arguments == child.arguments))
|
62
|
-
yield child
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
# grep all the recursive child nodes with conditions, and yield the first match node.
|
68
|
-
#
|
69
|
-
# @param [Hash] options grep conditions
|
70
|
-
#
|
71
|
-
# options is the grep conditions, like
|
72
|
-
#
|
73
|
-
# :node_type => :call,
|
74
|
-
# :subject => s(:const, Post),
|
75
|
-
# :message => [:find, :new],
|
76
|
-
# :arguments => s(:arglist)
|
77
|
-
#
|
78
|
-
# the condition key is one of :node_type, :subject, :message or :arguments,
|
79
|
-
# the condition value can be Symbol, Array or Sexp.
|
80
|
-
def grep_node(options)
|
81
|
-
grep_nodes(options) { |node| return node }
|
82
|
-
end
|
83
|
-
|
84
|
-
# grep all the recursive child nodes with conditions, and get the count of match nodes.
|
85
|
-
#
|
86
|
-
# @param [Hash] options grep conditions
|
87
|
-
# @return [Integer] the count of metch nodes
|
88
|
-
def grep_nodes_count(options)
|
89
|
-
count = 0
|
90
|
-
grep_nodes(options) { |node| count += 1 }
|
91
|
-
count
|
92
|
-
end
|
93
|
-
|
94
|
-
# Get subject of attrasgan, call and iter node.
|
95
|
-
#
|
96
|
-
# s(:attrasgn,
|
97
|
-
# s(:call, nil, :user, s(:arglist)),
|
98
|
-
# :name=,
|
99
|
-
# s(:arglist,
|
100
|
-
# s(:call,
|
101
|
-
# s(:call, nil, :params, s(:arglist)),
|
102
|
-
# :[],
|
103
|
-
# s(:arglist, s(:lit, :name))
|
104
|
-
# )
|
105
|
-
# )
|
106
|
-
# )
|
107
|
-
# => s(:call, nil, :user, s(:arglist))
|
108
|
-
#
|
109
|
-
# s(:call,
|
110
|
-
# s(:call, nil, :user, s(:arglist)),
|
111
|
-
# :name,
|
112
|
-
# s(:arglist)
|
113
|
-
# )
|
114
|
-
# => s(:call, nil, :user, s(:arglist))
|
115
|
-
#
|
116
|
-
# s(:iter,
|
117
|
-
# s(:call, s(:ivar, :@users), :each, s(:arglist)),
|
118
|
-
# s(:lasgn, :user),
|
119
|
-
# s(:call, nil, :p,
|
120
|
-
# s(:arglist, s(:lvar, :user))
|
121
|
-
# )
|
122
|
-
# )
|
123
|
-
# => s(:call, :s(:ivar, ;@users), :each, s(:arglist))
|
124
|
-
#
|
125
|
-
# @return [Sexp] subject of attrasgn, call or iter node
|
126
|
-
def subject
|
127
|
-
if [:attrasgn, :call, :iter].include? node_type
|
128
|
-
self[1]
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
# Get the class name of the class node.
|
133
|
-
#
|
134
|
-
# s(:class, :User, nil, s(:scope))
|
135
|
-
# => :User
|
136
|
-
#
|
137
|
-
# @return [Symbol] class name of class node
|
138
|
-
def class_name
|
139
|
-
if :class == node_type
|
140
|
-
self[1]
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
# Get the base class of the class node.
|
145
|
-
#
|
146
|
-
# s(:class, :User, s(:colon2, s(:const, :ActiveRecord), :Base), s(:scope))
|
147
|
-
# => s(:colon2, s(:const, :ActiveRecord), :Base)
|
148
|
-
#
|
149
|
-
# @return [Sexp] base class of class node
|
150
|
-
def base_class
|
151
|
-
if :class == node_type
|
152
|
-
self[2]
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
# Get the left value of the lasgn or iasgn node.
|
157
|
-
#
|
158
|
-
# s(:lasgn,
|
159
|
-
# :user,
|
160
|
-
# s(:call,
|
161
|
-
# s(:call, nil, :params, s(:arglist)),
|
162
|
-
# :[],
|
163
|
-
# s(:arglist, s(:lit, :user))
|
164
|
-
# )
|
165
|
-
# )
|
166
|
-
# => :user
|
167
|
-
#
|
168
|
-
# s(:iasgn,
|
169
|
-
# :@user,
|
170
|
-
# s(:call,
|
171
|
-
# s(:call, nil, :params, s(:arglist)),
|
172
|
-
# :[],
|
173
|
-
# s(:arglist, s(:lit, :user))
|
174
|
-
# )
|
175
|
-
# )
|
176
|
-
# => :@user
|
177
|
-
#
|
178
|
-
# @return [Symbol] left value of lasgn or iasgn node
|
179
|
-
def left_value
|
180
|
-
if [:lasgn, :iasgn].include? node_type
|
181
|
-
self[1]
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
# Get the right value of lasgn and iasgn node.
|
186
|
-
#
|
187
|
-
# s(:lasgn,
|
188
|
-
# :user,
|
189
|
-
# s(:call, nil, :current_user, s(:arglist))
|
190
|
-
# )
|
191
|
-
# => s(:call, nil, :current_user, s(:arglist))
|
192
|
-
#
|
193
|
-
# s(:iasgn,
|
194
|
-
# :@user,
|
195
|
-
# s(:call, nil, :current_user, s(:arglist))
|
196
|
-
# )
|
197
|
-
# => s(:call, nil, :current_user, s(:arglist))
|
198
|
-
#
|
199
|
-
# @return [Sexp] right value of lasgn or iasgn node
|
200
|
-
def right_value
|
201
|
-
if [:lasgn, :iasgn].include? node_type
|
202
|
-
self[2]
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
# Get the message of attrasgn and call node.
|
207
|
-
#
|
208
|
-
# s(:attrasgn,
|
209
|
-
# s(:call, nil, :user, s(:arglist)),
|
210
|
-
# :name=,
|
211
|
-
# s(:arglist,
|
212
|
-
# s(:call,
|
213
|
-
# s(:call, nil, :params, s(:arglist)),
|
214
|
-
# :[],
|
215
|
-
# s(:arglist, s(:lit, :name))
|
216
|
-
# )
|
217
|
-
# )
|
218
|
-
# )
|
219
|
-
# => :name=
|
220
|
-
#
|
221
|
-
# s(:call, nil, :has_many, s(:arglist, s(:lit, :projects)))
|
222
|
-
# => :has_many
|
223
|
-
#
|
224
|
-
# @return [Symbol] message of attrasgn or call node
|
225
|
-
def message
|
226
|
-
if [:attrasgn, :call].include? node_type
|
227
|
-
self[2]
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
# Get arguments of call node.
|
232
|
-
#
|
233
|
-
# s(:attrasgn,
|
234
|
-
# s(:call, nil, :post, s(:arglist)),
|
235
|
-
# :user=,
|
236
|
-
# s(:arglist,
|
237
|
-
# s(:call, nil, :current_user, s(:arglist))
|
238
|
-
# )
|
239
|
-
# )
|
240
|
-
# => s(:arglist, s(:call, nil, :current_user, s(:arglist)))
|
241
|
-
#
|
242
|
-
# s(:call,
|
243
|
-
# s(:call, nil, :username, s(:arglist)),
|
244
|
-
# :==,
|
245
|
-
# s(:arglist, s(:str, ""))
|
246
|
-
# )
|
247
|
-
# => s(:arglist, s(:str, ""))
|
248
|
-
#
|
249
|
-
# @return [Sexp] arguments of attrasgn or call node
|
250
|
-
def arguments
|
251
|
-
if [:attrasgn, :call].include? node_type
|
252
|
-
self[3]
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
# Get the conditional statement of if node.
|
257
|
-
#
|
258
|
-
# s(:if,
|
259
|
-
# s(:call,
|
260
|
-
# s(:call, nil, :current_user, s(:arglist)),
|
261
|
-
# :present?,
|
262
|
-
# s(:arglist)
|
263
|
-
# ),
|
264
|
-
# s(:call, nil, :puts,
|
265
|
-
# s(:arglist,
|
266
|
-
# s(:call,
|
267
|
-
# s(:call, nil, :current_user, s(:arglist)),
|
268
|
-
# :login,
|
269
|
-
# s(:arglist)
|
270
|
-
# )
|
271
|
-
# )
|
272
|
-
# ),
|
273
|
-
# nil
|
274
|
-
# )
|
275
|
-
# => s(:call, s(:call, nil, :current_user, s(:arglist)), :present?, s(:arglist))
|
276
|
-
#
|
277
|
-
# @return [Sexp] conditional statement of if node
|
278
|
-
def conditional_statement
|
279
|
-
if :if == node_type
|
280
|
-
self[1]
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
|
-
# Get the body node when conditional statement is true.
|
285
|
-
#
|
286
|
-
# s(:if,
|
287
|
-
# s(:call, s(:call, nil, :current_user, s(:arglist)), :login?, s(:arglist)),
|
288
|
-
# s(:call, s(:call, nil, :current_user, s(:arglist)), :login, s(:arglist)),
|
289
|
-
# s(:call, s(:call, nil, :current_user, s(:arglist)), :email, s(:arglist))
|
290
|
-
# )
|
291
|
-
# => s(:call, s(:call, nil, :current_user, s(:arglist)), :login, s(:arglist))
|
292
|
-
#
|
293
|
-
# @return [Sexp] the body node when conditional statement is true
|
294
|
-
def true_node
|
295
|
-
if :if == node_type
|
296
|
-
self[2]
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
|
-
# Get the body node when conditional statement is false.
|
301
|
-
#
|
302
|
-
# s(:if,
|
303
|
-
# s(:call, s(:call, nil, :current_user, s(:arglist)), :login?, s(:arglist)),
|
304
|
-
# s(:call, s(:call, nil, :current_user, s(:arglist)), :login, s(:arglist)),
|
305
|
-
# s(:call, s(:call, nil, :current_user, s(:arglist)), :email, s(:arglist))
|
306
|
-
# )
|
307
|
-
# => s(:call, s(:call, nil, :current_user, s(:arglist)), :email, s(:arglist))
|
308
|
-
#
|
309
|
-
# @return [Sexp] the body node when conditional statement is false
|
310
|
-
def false_node
|
311
|
-
if :if == node_type
|
312
|
-
self[3]
|
313
|
-
end
|
314
|
-
end
|
315
|
-
|
316
|
-
# Get the method name of defn node.
|
317
|
-
#
|
318
|
-
# s(:defn, :show, s(:args), s(:scope, s(:block, s(:nil))))
|
319
|
-
# => :show
|
320
|
-
#
|
321
|
-
# @return [Symbol] method name of defn node
|
322
|
-
def method_name
|
323
|
-
if :defn == node_type
|
324
|
-
self[1]
|
325
|
-
end
|
326
|
-
end
|
327
|
-
|
328
|
-
# Get body of iter, class and defn node.
|
329
|
-
#
|
330
|
-
# s(:iter,
|
331
|
-
# s(:call, nil, :resources, s(:arglist, s(:lit, :posts))),
|
332
|
-
# nil,
|
333
|
-
# s(:call, nil, :resources, s(:arglist, s(:lit, :comments)))
|
334
|
-
# )
|
335
|
-
# => s(:call, nil, :resources, s(:arglist, s(:lit, :comments)))
|
336
|
-
#
|
337
|
-
# s(:class, :User, nil,
|
338
|
-
# s(:scope,
|
339
|
-
# s(:block,
|
340
|
-
# s(:defn, :login, s(:args), s(:scope, s(:block, s(:nil)))),
|
341
|
-
# s(:defn, :email, s(:args), s(:scope, s(:block, s(:nil))))
|
342
|
-
# )
|
343
|
-
# )
|
344
|
-
# )
|
345
|
-
# => s(:block,
|
346
|
-
# s(:defn, :login, s(:args), s(:scope, s(:block, s(:nil)))),
|
347
|
-
# s(:defn, :email, s(:args), s(:scope, s(:block, s(:nil))))
|
348
|
-
# )
|
349
|
-
#
|
350
|
-
# s(:defn, :fullname, s(:args),
|
351
|
-
# s(:scope,
|
352
|
-
# s(:block,
|
353
|
-
# s(:call,
|
354
|
-
# s(:call,
|
355
|
-
# s(:call, nil, :first_name, s(:arglist)),
|
356
|
-
# :+,
|
357
|
-
# s(:arglist,
|
358
|
-
# s(:call, nil, :last, s(:arglist))
|
359
|
-
# )
|
360
|
-
# ),
|
361
|
-
# :+,
|
362
|
-
# s(:arglist,
|
363
|
-
# s(:call, nil, :name, s(:arglist))
|
364
|
-
# )
|
365
|
-
# )
|
366
|
-
# )
|
367
|
-
# )
|
368
|
-
# )
|
369
|
-
# => s(:block,
|
370
|
-
# s(:call,
|
371
|
-
# s(:call,
|
372
|
-
# s(:call, nil, :first_name, s(:arglist)),
|
373
|
-
# :+,
|
374
|
-
# s(:arglist,
|
375
|
-
# s(:call, nil, :last, s(:arglist))
|
376
|
-
# )
|
377
|
-
# ),
|
378
|
-
# :+,
|
379
|
-
# s(:arglist,
|
380
|
-
# s(:call, nil, :name, s(:arglist))
|
381
|
-
# )
|
382
|
-
# )
|
383
|
-
# )
|
384
|
-
#
|
385
|
-
# @return [Sexp] body of iter, class or defn node
|
386
|
-
def body
|
387
|
-
if :iter == node_type
|
388
|
-
self[3]
|
389
|
-
elsif :class == node_type
|
390
|
-
self[3][1]
|
391
|
-
elsif :module == node_type
|
392
|
-
self[2][1]
|
393
|
-
elsif :defn == node_type
|
394
|
-
self[3][1]
|
395
|
-
end
|
396
|
-
end
|
397
|
-
|
398
|
-
# to_s for lvar, ivar, lit, const, array, hash, and colon2 node.
|
399
|
-
#
|
400
|
-
# @param [Hash] options
|
401
|
-
# :remove_at remove the @ symbol for ivar.
|
402
|
-
# @return [String] to_s
|
403
|
-
def to_s(options={})
|
404
|
-
case node_type
|
405
|
-
when :true, :false, :nil
|
406
|
-
self[0].to_s
|
407
|
-
when :ivar
|
408
|
-
options[:remove_at] ? self[1].to_s[1..-1] : self[1].to_s
|
409
|
-
when :lvar, :str, :lit, :const
|
410
|
-
self[1].to_s
|
411
|
-
when :array
|
412
|
-
"[\"#{self.children.collect(&:to_s).join('", "')}\"]"
|
413
|
-
when :hash
|
414
|
-
key_value = false # false is key, true is value
|
415
|
-
result = ['{']
|
416
|
-
children.each do |child|
|
417
|
-
if [:true, :false, :nil, :array, :hash].include? child.node_type
|
418
|
-
result << "#{child}"
|
419
|
-
else
|
420
|
-
result << "\"#{child}\""
|
421
|
-
end
|
422
|
-
result << (key_value ? ", " : " => ")
|
423
|
-
key_value = !key_value
|
424
|
-
end
|
425
|
-
result.join("").sub(/, $/, '') + '}'
|
426
|
-
when :colon2
|
427
|
-
"#{self[1]}::#{self[2]}"
|
428
|
-
else
|
429
|
-
""
|
430
|
-
end
|
431
|
-
end
|
432
|
-
|
433
|
-
# if the return value of these methods is nil, then return RailsBestPractices::Core::Nil.new instead
|
434
|
-
[:node_type, :subject, :message, :arguments, :class_name, :base_class, :method_name, :body, :conditional_statement, :true_node, :false_node, :left_value, :right_value].each do |method|
|
435
|
-
class_eval <<-EOS
|
436
|
-
alias_method :origin_#{method}, :#{method}
|
437
|
-
|
438
|
-
def #{method}
|
439
|
-
ret = origin_#{method}
|
440
|
-
ret.nil? ? RailsBestPractices::Core::Nil.new : ret
|
441
|
-
end
|
442
|
-
EOS
|
443
|
-
end
|
444
|
-
end
|