rails_best_practices 0.10.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/README.md +20 -0
  2. data/assets/result.html.haml +1 -1
  3. data/lib/rails_best_practices.rb +5 -3
  4. data/lib/rails_best_practices/core.rb +1 -1
  5. data/lib/rails_best_practices/core/check.rb +9 -12
  6. data/lib/rails_best_practices/core/checking_visitor.rb +9 -6
  7. data/lib/rails_best_practices/core/model_associations.rb +1 -1
  8. data/lib/rails_best_practices/core/nil.rb +5 -1
  9. data/lib/rails_best_practices/core/runner.rb +5 -5
  10. data/lib/rails_best_practices/core_ext/sexp.rb +688 -0
  11. data/lib/rails_best_practices/prepares/mailer_prepare.rb +4 -5
  12. data/lib/rails_best_practices/prepares/model_prepare.rb +16 -26
  13. data/lib/rails_best_practices/prepares/schema_prepare.rb +11 -17
  14. data/lib/rails_best_practices/reviews/add_model_virtual_attribute_review.rb +24 -75
  15. data/lib/rails_best_practices/reviews/always_add_db_index_review.rb +39 -113
  16. data/lib/rails_best_practices/reviews/dry_bundler_in_capistrano_review.rb +6 -16
  17. data/lib/rails_best_practices/reviews/isolate_seed_data_review.rb +16 -32
  18. data/lib/rails_best_practices/reviews/keep_finders_on_their_own_model_review.rb +11 -20
  19. data/lib/rails_best_practices/reviews/law_of_demeter_review.rb +7 -28
  20. data/lib/rails_best_practices/reviews/move_code_into_controller_review.rb +16 -14
  21. data/lib/rails_best_practices/reviews/move_code_into_helper_review.rb +10 -28
  22. data/lib/rails_best_practices/reviews/move_code_into_model_review.rb +12 -11
  23. data/lib/rails_best_practices/reviews/move_finder_to_named_scope_review.rb +13 -24
  24. data/lib/rails_best_practices/reviews/move_model_logic_into_model_review.rb +9 -9
  25. data/lib/rails_best_practices/reviews/needless_deep_nesting_review.rb +24 -68
  26. data/lib/rails_best_practices/reviews/not_use_default_route_review.rb +15 -22
  27. data/lib/rails_best_practices/reviews/overuse_route_customizations_review.rb +31 -91
  28. data/lib/rails_best_practices/reviews/remove_empty_helpers_review.rb +4 -2
  29. data/lib/rails_best_practices/reviews/replace_complex_creation_with_factory_method_review.rb +20 -18
  30. data/lib/rails_best_practices/reviews/replace_instance_variable_with_local_variable_review.rb +5 -3
  31. data/lib/rails_best_practices/reviews/review.rb +8 -37
  32. data/lib/rails_best_practices/reviews/simplify_render_in_controllers_review.rb +10 -6
  33. data/lib/rails_best_practices/reviews/simplify_render_in_views_review.rb +9 -6
  34. data/lib/rails_best_practices/reviews/use_before_filter_review.rb +14 -72
  35. data/lib/rails_best_practices/reviews/use_model_association_review.rb +19 -31
  36. data/lib/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review.rb +5 -5
  37. data/lib/rails_best_practices/reviews/use_observer_review.rb +22 -40
  38. data/lib/rails_best_practices/reviews/use_query_attribute_review.rb +34 -39
  39. data/lib/rails_best_practices/reviews/use_say_with_time_in_migrations_review.rb +14 -38
  40. data/lib/rails_best_practices/reviews/use_scope_access_review.rb +13 -44
  41. data/lib/rails_best_practices/version.rb +1 -1
  42. data/spec/rails_best_practices/core/check_spec.rb +5 -5
  43. data/spec/rails_best_practices/core/checking_visitor_spec.rb +4 -4
  44. data/spec/rails_best_practices/core/model_associations_spec.rb +4 -4
  45. data/spec/rails_best_practices/core/nil_spec.rb +7 -1
  46. data/spec/rails_best_practices/core_ext/sexp_spec.rb +430 -0
  47. data/spec/rails_best_practices/prepares/model_prepare_spec.rb +12 -12
  48. data/spec/rails_best_practices/prepares/schema_prepare_spec.rb +6 -6
  49. data/spec/rails_best_practices/reviews/move_code_into_controller_review_spec.rb +14 -2
  50. data/spec/rails_best_practices/reviews/move_code_into_helper_review_spec.rb +1 -1
  51. data/spec/rails_best_practices/reviews/needless_deep_nesting_review_spec.rb +3 -3
  52. data/spec/rails_best_practices/reviews/not_use_default_route_review_spec.rb +1 -1
  53. data/spec/rails_best_practices/reviews/overuse_route_customizations_review_spec.rb +15 -1
  54. data/spec/rails_best_practices/reviews/simplify_render_in_controllers_review_spec.rb +3 -3
  55. data/spec/rails_best_practices/reviews/use_query_attribute_review_spec.rb +1 -1
  56. data/spec/rails_best_practices/reviews/use_say_with_time_in_migrations_review_spec.rb +1 -1
  57. data/spec/rails_best_practices/reviews/use_scope_access_review_spec.rb +4 -4
  58. data/spec/rails_best_practices_spec.rb +1 -3
  59. data/spec/spec_helper.rb +4 -0
  60. metadata +6 -8
  61. data/lib/rails_best_practices/core/visitable_sexp.rb +0 -444
  62. data/spec/rails_best_practices/core/visitable_sexp_spec.rb +0 -272
  63. 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 == {: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"}
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, :class_name => "Person"
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 == {:meta => :belongs_to, :class_name => "Person"}
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, :class_name => "Person"
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 == {:meta => :has_one, :class_name => "Person"}
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, :class_name => "Person"
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 == {:meta => :has_many, :class_name => "Person"}
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, :class_name => "Country"
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 == {:meta => :has_and_belongs_to_many, :class_name => "Country"}
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 == :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
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
- <% @posts = Post.find(:all) %>
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:3 - move code into helper (array_count >= 2)"
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:4 - needless deep nesting (nested_count > 2)"
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:4 - needless deep nesting (nested_count > 2)"
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:4 - needless deep nesting (nested_count > 2)"
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:5 - not use default route"
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 2" do
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:3 - simplify render in controllers"
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:3 - simplify render in controllers"
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:3 - simplify render in controllers"
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? and @user.login.present? %>
80
+ <% if @user.active? && @user.login.present? %>
81
81
  <%= @user.login %>
82
82
  <% end %>
83
83
  EOF
@@ -113,6 +113,6 @@ describe RailsBestPractices::Reviews::UseSayWithTimeInMigrationsReview do
113
113
  end
114
114
  EOF
115
115
  runner.review('db/migrate/20101010080658_create_users.rb', content)
116
- runner.should have(0).errors
116
+ runner.should have(3).errors
117
117
  end
118
118
  end
@@ -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:7 - use scope access"
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:7 - use scope access"
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:7 - use scope access"
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:7 - use scope access"
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 errors.".red].join("\n") + "\n"
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
@@ -3,3 +3,7 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
3
3
 
4
4
  require 'rspec/expectations'
5
5
  require 'rails_best_practices'
6
+
7
+ def parse_content(content)
8
+ Sexp.from_array(Ripper::SexpBuilder.new(content).parse)[1]
9
+ end
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.10.1
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-07-16 00:00:00 +09:00
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: -1121248838931870428
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