rails_best_practices 0.6.6 → 0.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. data/Gemfile +0 -1
  2. data/README.md +28 -24
  3. data/Rakefile +0 -8
  4. data/install_supported_rubies.sh +2 -3
  5. data/lib/rails_best_practices.rb +8 -7
  6. data/lib/rails_best_practices/core.rb +1 -0
  7. data/lib/rails_best_practices/core/check.rb +68 -0
  8. data/lib/rails_best_practices/core/checking_visitor.rb +18 -15
  9. data/lib/rails_best_practices/core/runner.rb +22 -12
  10. data/lib/rails_best_practices/core/visitable_sexp.rb +6 -2
  11. data/lib/rails_best_practices/prepares.rb +11 -0
  12. data/lib/rails_best_practices/prepares/mailer_prepare.rb +33 -0
  13. data/lib/rails_best_practices/prepares/model_prepare.rb +60 -0
  14. data/lib/rails_best_practices/reviews.rb +23 -0
  15. data/lib/rails_best_practices/{checks/add_model_virtual_attribute_check.rb → reviews/add_model_virtual_attribute_review.rb} +6 -9
  16. data/lib/rails_best_practices/{checks/always_add_db_index_check.rb → reviews/always_add_db_index_review.rb} +9 -12
  17. data/lib/rails_best_practices/{checks/dry_bundler_in_capistrano_check.rb → reviews/dry_bundler_in_capistrano_review.rb} +8 -11
  18. data/lib/rails_best_practices/{checks/isolate_seed_data_check.rb → reviews/isolate_seed_data_review.rb} +11 -14
  19. data/lib/rails_best_practices/{checks/keep_finders_on_their_own_model_check.rb → reviews/keep_finders_on_their_own_model_review.rb} +7 -10
  20. data/lib/rails_best_practices/{checks/law_of_demeter_check.rb → reviews/law_of_demeter_review.rb} +10 -14
  21. data/lib/rails_best_practices/{checks/move_code_into_controller_check.rb → reviews/move_code_into_controller_review.rb} +8 -11
  22. data/lib/rails_best_practices/{checks/move_code_into_helper_check.rb → reviews/move_code_into_helper_review.rb} +7 -10
  23. data/lib/rails_best_practices/{checks/move_code_into_model_check.rb → reviews/move_code_into_model_review.rb} +7 -10
  24. data/lib/rails_best_practices/{checks/move_finder_to_named_scope_check.rb → reviews/move_finder_to_named_scope_review.rb} +7 -10
  25. data/lib/rails_best_practices/{checks/move_model_logic_into_model_check.rb → reviews/move_model_logic_into_model_review.rb} +8 -11
  26. data/lib/rails_best_practices/{checks/needless_deep_nesting_check.rb → reviews/needless_deep_nesting_review.rb} +8 -11
  27. data/lib/rails_best_practices/{checks/not_use_default_route_check.rb → reviews/not_use_default_route_review.rb} +7 -10
  28. data/lib/rails_best_practices/{checks/overuse_route_customizations_check.rb → reviews/overuse_route_customizations_review.rb} +10 -13
  29. data/lib/rails_best_practices/{checks/replace_complex_creation_with_factory_method_check.rb → reviews/replace_complex_creation_with_factory_method_review.rb} +8 -11
  30. data/lib/rails_best_practices/{checks/replace_instance_variable_with_local_variable_check.rb → reviews/replace_instance_variable_with_local_variable_review.rb} +7 -10
  31. data/lib/rails_best_practices/reviews/review.rb +92 -0
  32. data/lib/rails_best_practices/{checks/use_before_filter_check.rb → reviews/use_before_filter_review.rb} +8 -11
  33. data/lib/rails_best_practices/{checks/use_model_association_check.rb → reviews/use_model_association_review.rb} +8 -11
  34. data/lib/rails_best_practices/{checks/use_observer_check.rb → reviews/use_observer_review.rb} +14 -41
  35. data/lib/rails_best_practices/{checks/use_query_attribute_check.rb → reviews/use_query_attribute_review.rb} +20 -16
  36. data/lib/rails_best_practices/{checks/use_say_with_time_in_migrations_check.rb → reviews/use_say_with_time_in_migrations_review.rb} +8 -11
  37. data/lib/rails_best_practices/{checks/use_scope_access_check.rb → reviews/use_scope_access_review.rb} +8 -11
  38. data/lib/rails_best_practices/version.rb +1 -1
  39. data/rails_best_practices.gemspec +3 -2
  40. data/rails_best_practices.yml +22 -22
  41. data/rake_rubies.sh +3 -2
  42. data/spec/rails_best_practices/core/check_spec.rb +41 -0
  43. data/spec/rails_best_practices/core/checking_visitor_spec.rb +78 -0
  44. data/spec/rails_best_practices/core/visitable_sexp_spec.rb +39 -36
  45. data/spec/rails_best_practices/prepares/mailer_prepare_spec.rb +14 -0
  46. data/spec/rails_best_practices/prepares/model_prepare_spec.rb +22 -0
  47. data/spec/rails_best_practices/{checks/add_model_virtual_attribute_check_spec.rb → reviews/add_model_virtual_attribute_review_spec.rb} +17 -25
  48. data/spec/rails_best_practices/{checks/always_add_db_index_check_spec.rb → reviews/always_add_db_index_review_spec.rb} +28 -41
  49. data/spec/rails_best_practices/{checks/dry_bundler_in_capistrano_check_spec.rb → reviews/dry_bundler_in_capistrano_review_spec.rb} +7 -11
  50. data/spec/rails_best_practices/{checks/isolate_seed_data_check_spec.rb → reviews/isolate_seed_data_review_spec.rb} +13 -20
  51. data/spec/rails_best_practices/{checks/keep_finders_on_their_own_model_check_spec.rb → reviews/keep_finders_on_their_own_model_review_spec.rb} +16 -24
  52. data/spec/rails_best_practices/{checks/law_of_demeter_check_spec.rb → reviews/law_of_demeter_review_spec.rb} +24 -26
  53. data/spec/rails_best_practices/reviews/move_code_into_controller_review_spec.rb +29 -0
  54. data/spec/rails_best_practices/reviews/move_code_into_helper_review_spec.rb +24 -0
  55. data/spec/rails_best_practices/{checks/move_code_into_model_check_spec.rb → reviews/move_code_into_model_review_spec.rb} +12 -18
  56. data/spec/rails_best_practices/{checks/move_finder_to_named_scope_check_spec.rb → reviews/move_finder_to_named_scope_review_spec.rb} +12 -16
  57. data/spec/rails_best_practices/{checks/move_model_logic_into_model_check_spec.rb → reviews/move_model_logic_into_model_review_spec.rb} +7 -11
  58. data/spec/rails_best_practices/{checks/needless_deep_nesting_check_spec.rb → reviews/needless_deep_nesting_review_spec.rb} +26 -37
  59. data/spec/rails_best_practices/{checks/not_use_default_route_check_spec.rb → reviews/not_use_default_route_review_spec.rb} +13 -19
  60. data/spec/rails_best_practices/{checks/overuse_route_customizations_check_spec.rb → reviews/overuse_route_customizations_review_spec.rb} +27 -39
  61. data/spec/rails_best_practices/{checks/replace_complex_creation_with_factory_method_check_spec.rb → reviews/replace_complex_creation_with_factory_method_review_spec.rb} +10 -15
  62. data/spec/rails_best_practices/reviews/replace_instance_variable_with_local_variable_review_spec.rb +31 -0
  63. data/spec/rails_best_practices/reviews/review_spec.rb +11 -0
  64. data/spec/rails_best_practices/{checks/use_before_filter_check_spec.rb → reviews/use_before_filter_review_spec.rb} +11 -17
  65. data/spec/rails_best_practices/{checks/use_model_association_check_spec.rb → reviews/use_model_association_review_spec.rb} +12 -18
  66. data/spec/rails_best_practices/{checks/use_observer_check_spec.rb → reviews/use_observer_review_spec.rb} +28 -29
  67. data/spec/rails_best_practices/reviews/use_query_attribute_review_spec.rb +190 -0
  68. data/spec/rails_best_practices/{checks/use_say_with_time_in_migrations_check_spec.rb → reviews/use_say_with_time_in_migrations_review_spec.rb} +14 -23
  69. data/spec/rails_best_practices/{checks/use_scope_access_check_spec.rb → reviews/use_scope_access_review_spec.rb} +28 -37
  70. data/spec/rails_best_practices_spec.rb +4 -4
  71. data/spec/spec_helper.rb +1 -0
  72. metadata +128 -102
  73. data/lib/rails_best_practices/checks.rb +0 -23
  74. data/lib/rails_best_practices/checks/check.rb +0 -203
  75. data/spec/rails_best_practices/checks/check_spec.rb +0 -57
  76. data/spec/rails_best_practices/checks/move_code_into_controller_check_spec.rb +0 -33
  77. data/spec/rails_best_practices/checks/move_code_into_helper_check_spec.rb +0 -28
  78. data/spec/rails_best_practices/checks/replace_instance_variable_with_local_variable_check_spec.rb +0 -36
  79. data/spec/rails_best_practices/checks/use_query_attribute_check_spec.rb +0 -192
@@ -1,31 +1,28 @@
1
1
  # encoding: utf-8
2
- require 'rails_best_practices/checks/check'
2
+ require 'rails_best_practices/reviews/review'
3
3
 
4
4
  module RailsBestPractices
5
- module Checks
6
- # Check a view file to make sure there is no complex logic call for model.
5
+ module Reviews
6
+ # Review a view file to make sure there is no complex logic call for model.
7
7
  #
8
8
  # See the best practice details here http://rails-bestpractices.com/posts/25-move-code-into-model.
9
9
  #
10
10
  # Implementation:
11
11
  #
12
- # Prepare process:
13
- # none
14
- #
15
12
  # Review process:
16
13
  # check if there are multiple method calls or attribute assignments apply to one subject,
17
14
  # and the subject is a local variable or instance variable,
18
15
  # then they should be moved into model.
19
- class MoveCodeIntoModelCheck < Check
16
+ class MoveCodeIntoModelReview < Review
20
17
  def url
21
18
  "http://rails-bestpractices.com/posts/25-move-code-into-model"
22
19
  end
23
20
 
24
- def interesting_review_nodes
21
+ def interesting_nodes
25
22
  [:if]
26
23
  end
27
24
 
28
- def interesting_review_files
25
+ def interesting_files
29
26
  VIEW_FILES
30
27
  end
31
28
 
@@ -41,7 +38,7 @@ module RailsBestPractices
41
38
  # if there are multiple call and attrasgn nodes who have the same subject,
42
39
  # and the subject is a local variable or an instance variable,
43
40
  # then the conditional statement nodes should be moved into model.
44
- def review_start_if(node)
41
+ def start_if(node)
45
42
  node.conditional_statement.grep_nodes(:node_type => [:call, :attrasgn]) { |child_node| remember_variable_use_count(child_node) }
46
43
 
47
44
  variable_use_count.each do |variable_node, count|
@@ -1,23 +1,20 @@
1
1
  # encoding: utf-8
2
- require 'rails_best_practices/checks/check'
2
+ require 'rails_best_practices/reviews/review'
3
3
 
4
4
  module RailsBestPractices
5
- module Checks
6
- # Check a controller file to make sure there are no complex finder.
5
+ module Reviews
6
+ # Review a controller file to make sure there are no complex finder.
7
7
  #
8
8
  # See the best practice details here http://rails-bestpractices.com/posts/1-move-finder-to-named_scope.
9
9
  #
10
10
  # Implementation:
11
11
  #
12
- # Prepare process:
13
- # none
14
- #
15
12
  # Review process:
16
13
  # check all method calls in controller files.
17
14
  # if there is any call node with message find, all, first or last,
18
15
  # and it has a hash argument,
19
16
  # then it is a complex finder, and should be moved to model's named scope.
20
- class MoveFinderToNamedScopeCheck < Check
17
+ class MoveFinderToNamedScopeReview < Review
21
18
 
22
19
  FINDER = [:find, :all, :first, :last]
23
20
 
@@ -25,18 +22,18 @@ module RailsBestPractices
25
22
  "http://rails-bestpractices.com/posts/1-move-finder-to-named_scope"
26
23
  end
27
24
 
28
- def interesting_review_nodes
25
+ def interesting_nodes
29
26
  [:call]
30
27
  end
31
28
 
32
- def interesting_review_files
29
+ def interesting_files
33
30
  CONTROLLER_FILES
34
31
  end
35
32
 
36
33
  # check call node if its message is one of :find, :all, :first or :last,
37
34
  # and it has a hash argument,
38
35
  # then the call node is the finder that should be moved to model's named_scope.
39
- def review_start_call(node)
36
+ def start_call(node)
40
37
  add_error "move finder to named_scope" if finder?(node)
41
38
  end
42
39
 
@@ -1,32 +1,29 @@
1
1
  # encoding: utf-8
2
- require 'rails_best_practices/checks/check'
2
+ require 'rails_best_practices/reviews/review'
3
3
 
4
4
  module RailsBestPractices
5
- module Checks
6
- # Check a controller file to make sure that complex model logic should not exist in controller, should be moved into a model.
5
+ module Reviews
6
+ # Review a controller file to make sure that complex model logic should not exist in controller, should be moved into a model.
7
7
  #
8
8
  # See the best practice details here http://rails-bestpractices.com/posts/7-move-model-logic-into-the-model.
9
9
  #
10
10
  # Implementation:
11
11
  #
12
- # Prepare process:
13
- # none
14
- #
15
12
  # Review process:
16
13
  # check all method defines in the controller files,
17
14
  # if there are multiple method calls or attribute assignments apply to one subject,
18
15
  # and the subject is a local variable or an instance variable,
19
16
  # then they are complex model logic, and they should be moved into model.
20
- class MoveModelLogicIntoModelCheck < Check
17
+ class MoveModelLogicIntoModelReview < Review
21
18
  def url
22
19
  "http://rails-bestpractices.com/posts/7-move-model-logic-into-the-model"
23
20
  end
24
21
 
25
- def interesting_review_nodes
22
+ def interesting_nodes
26
23
  [:defn]
27
24
  end
28
25
 
29
- def interesting_review_files
26
+ def interesting_files
30
27
  CONTROLLER_FILES
31
28
  end
32
29
 
@@ -35,13 +32,13 @@ module RailsBestPractices
35
32
  @use_count = options['use_count'] || 4
36
33
  end
37
34
 
38
- # check method define node to see if there are multiple method calls and attribute assignments (more than @use_count defined) on one local variable or instance varialbe in review process.
35
+ # check method define node to see if there are multiple method calls and attribute assignments (more than @use_count defined) on one local variable or instance varialbe.
39
36
  #
40
37
  # it will check every call and attrasgn nodes,
41
38
  # if there are multiple call and attrasgn nodes who have the same subject,
42
39
  # and the subject is a local variable or an instance variable,
43
40
  # then these method calls and attribute assignments should be moved into model.
44
- def review_start_defn(node)
41
+ def start_defn(node)
45
42
  node.grep_nodes(:node_type => [:call, :attrasgn]) do |child_node|
46
43
  remember_variable_use_count(child_node)
47
44
  end
@@ -1,17 +1,14 @@
1
1
  # encoding: utf-8
2
- require 'rails_best_practices/checks/check'
2
+ require 'rails_best_practices/reviews/review'
3
3
 
4
4
  module RailsBestPractices
5
- module Checks
6
- # Check config/routes.rb file to make sure not to use too deep nesting routes.
5
+ module Reviews
6
+ # Review config/routes.rb file to make sure not to use too deep nesting routes.
7
7
  #
8
8
  # See the best practice details here http://rails-bestpractices.com/posts/11-needless-deep-nesting.
9
9
  #
10
10
  # Implementation:
11
11
  #
12
- # Prepare process:
13
- # none
14
- #
15
12
  # Review process:
16
13
  # chech all iter nodes in route file.
17
14
  #
@@ -29,16 +26,16 @@ module RailsBestPractices
29
26
  # and the message of the node is :resources or :resource,
30
27
  # and the @counter is greater than @nested_count defined,
31
28
  # then it is a needless deep nesting.
32
- class NeedlessDeepNestingCheck < Check
29
+ class NeedlessDeepNestingReview < Review
33
30
  def url
34
31
  "http://rails-bestpractices.com/posts/11-needless-deep-nesting"
35
32
  end
36
33
 
37
- def interesting_review_nodes
34
+ def interesting_nodes
38
35
  [:call, :iter]
39
36
  end
40
37
 
41
- def interesting_review_files
38
+ def interesting_files
42
39
  ROUTE_FILE
43
40
  end
44
41
 
@@ -48,7 +45,7 @@ module RailsBestPractices
48
45
  @nested_count = options['nested_count'] || 2
49
46
  end
50
47
 
51
- # check all iter node in review process.
48
+ # check all iter node.
52
49
  #
53
50
  # It is a recursively check,
54
51
  #
@@ -76,7 +73,7 @@ module RailsBestPractices
76
73
  #
77
74
  # test if the @counter is greater than or equal to @nested_count,
78
75
  # if so, it is a needless deep nesting.
79
- def review_start_iter(node)
76
+ def start_iter(node)
80
77
  recursively_check(node)
81
78
  end
82
79
 
@@ -1,17 +1,14 @@
1
1
  # encoding: utf-8
2
- require 'rails_best_practices/checks/check'
2
+ require 'rails_best_practices/reviews/review'
3
3
 
4
4
  module RailsBestPractices
5
- module Checks
6
- # Check config/routes file to make sure not use default route that rails generated.
5
+ module Reviews
6
+ # Review config/routes file to make sure not use default route that rails generated.
7
7
  #
8
8
  # See the best practice details here http://rails-bestpractices.com/posts/12-not-use-default-route-if-you-use-restful-design
9
9
  #
10
10
  # Implementation:
11
11
  #
12
- # Prepare process:
13
- # none
14
- #
15
12
  # Review process:
16
13
  # check all method call to see if any method call is the same as rails default route.
17
14
  #
@@ -21,16 +18,16 @@ module RailsBestPractices
21
18
  # or
22
19
  #
23
20
  # match ':controller(/:action(/:id(.:format)))'
24
- class NotUseDefaultRouteCheck < Check
21
+ class NotUseDefaultRouteReview < Review
25
22
  def url
26
23
  "http://rails-bestpractices.com/posts/12-not-use-default-route-if-you-use-restful-design"
27
24
  end
28
25
 
29
- def interesting_review_nodes
26
+ def interesting_nodes
30
27
  [:call]
31
28
  end
32
29
 
33
- def interesting_review_files
30
+ def interesting_files
34
31
  ROUTE_FILE
35
32
  end
36
33
 
@@ -50,7 +47,7 @@ module RailsBestPractices
50
47
  # s(:call, nil, :match,
51
48
  # s(:arglist, s(:str, ":controller(/:action(/:id(.:format)))"))
52
49
  # )
53
- def review_start_call(node)
50
+ def start_call(node)
54
51
  if s(:call, s(:lvar, :map), :connect, s(:arglist, s(:str, ":controller/:action/:id"))) == node ||
55
52
  s(:call, s(:lvar, :map), :connect, s(:arglist, s(:str, ":controller/:action/:id.:format"))) == node ||
56
53
  s(:call, nil, :match, s(:arglist, s(:str, ":controller(/:action(/:id(.:format)))"))) == node
@@ -1,17 +1,14 @@
1
1
  # encoding: utf-8
2
- require 'rails_best_practices/checks/check'
2
+ require 'rails_best_practices/reviews/review'
3
3
 
4
4
  module RailsBestPractices
5
- module Checks
6
- # Check config/routes.rb file to make sure there are no overuse route customizations.
5
+ module Reviews
6
+ # Review config/routes.rb file to make sure there are no overuse route customizations.
7
7
  #
8
8
  # See the best practice details here http://rails-bestpractices.com/posts/10-overuse-route-customizations.
9
9
  #
10
10
  # Implementation:
11
11
  #
12
- # Prepare process:
13
- # none
14
- #
15
12
  # Review process:
16
13
  # the check methods are different for rails2 and rails3 syntax.
17
14
  #
@@ -30,7 +27,7 @@ module RailsBestPractices
30
27
  # and in the block body of iter node, there are more than @customize_count call nodes,
31
28
  # whose message is :get, :post, :update or :delete,
32
29
  # then these custom routes are overuse.
33
- class OveruseRouteCustomizationsCheck < Check
30
+ class OveruseRouteCustomizationsReview < Review
34
31
 
35
32
  VERBS = [:get, :post, :update, :delete]
36
33
 
@@ -38,11 +35,11 @@ module RailsBestPractices
38
35
  "http://rails-bestpractices.com/posts/10-overuse-route-customizations"
39
36
  end
40
37
 
41
- def interesting_review_nodes
38
+ def interesting_nodes
42
39
  [:call, :iter]
43
40
  end
44
41
 
45
- def interesting_review_files
42
+ def interesting_files
46
43
  ROUTE_FILE
47
44
  end
48
45
 
@@ -51,7 +48,7 @@ module RailsBestPractices
51
48
  @customize_count = options['customize_count'] || 3
52
49
  end
53
50
 
54
- # check call node to see if the count of member and collection custom routes is more than @customize_count defined in review process.
51
+ # check call node to see if the count of member and collection custom routes is more than @customize_count defined.
55
52
  # this is for rails2 syntax.
56
53
  #
57
54
  # if the message of call node is :resources,
@@ -64,13 +61,13 @@ module RailsBestPractices
64
61
  # :collection => { :comments => :get }
65
62
  #
66
63
  # then they are overuse route customizations.
67
- def review_start_call(node)
64
+ def start_call(node)
68
65
  if member_and_collection_count_for_rails2(node) > @customize_count
69
66
  add_error "overuse route customizations (customize_count > #{@customize_count})", node.file, node.subject.line
70
67
  end
71
68
  end
72
69
 
73
- # check iter node to see if the count of member and collection custom routes is more than @customize_count defined in review process.
70
+ # check iter node to see if the count of member and collection custom routes is more than @customize_count defined.
74
71
  # this is for rails3 syntax.
75
72
  #
76
73
  # if the subject of iter node is with message :resources,
@@ -90,7 +87,7 @@ module RailsBestPractices
90
87
  # end
91
88
  #
92
89
  # then they are overuse route customizations.
93
- def review_start_iter(node)
90
+ def start_iter(node)
94
91
  if member_and_collection_count_for_rails3(node) > @customize_count
95
92
  add_error "overuse route customizations (customize_count > #{@customize_count})", node.file, node.subject.line
96
93
  end
@@ -1,33 +1,30 @@
1
1
  # encoding: utf-8
2
- require 'rails_best_practices/checks/check'
2
+ require 'rails_best_practices/reviews/review'
3
3
 
4
4
  module RailsBestPractices
5
- module Checks
6
- # Check a controller file to make sure that complex model creation should not exist in controller, should be replaced with factory method.
5
+ module Reviews
6
+ # Review a controller file to make sure that complex model creation should not exist in controller, should be replaced with factory method.
7
7
  #
8
8
  # See the best practice details here http://rails-bestpractices.com/posts/6-replace-complex-creation-with-factory-method.
9
9
  #
10
10
  # Implementation:
11
11
  #
12
- # Prepare process:
13
- # none
14
- #
15
12
  # Review process:
16
13
  # check all method defines in the controller files,
17
14
  # if there are multiple attribute assignments apply to one subject,
18
15
  # and the subject is a local variable or an instance variable,
19
16
  # and after them there is a call node with message :save or :save!,
20
17
  # then these attribute assignments are complex creation, should be replaced with factory method.
21
- class ReplaceComplexCreationWithFactoryMethodCheck < Check
18
+ class ReplaceComplexCreationWithFactoryMethodReview < Review
22
19
  def url
23
20
  "http://rails-bestpractices.com/posts/6-replace-complex-creation-with-factory-method"
24
21
  end
25
22
 
26
- def interesting_review_nodes
23
+ def interesting_nodes
27
24
  [:defn]
28
25
  end
29
26
 
30
- def interesting_review_files
27
+ def interesting_files
31
28
  CONTROLLER_FILES
32
29
  end
33
30
 
@@ -36,14 +33,14 @@ module RailsBestPractices
36
33
  @attrasgn_count = options['attribute_assignment_count'] || 2
37
34
  end
38
35
 
39
- # check method define node to see if there are multiple attribute assignments, more than @attrasgn_count, on one local variable or instance variable before save in review process.
36
+ # check method define node to see if there are multiple attribute assignments, more than @attrasgn_count, on one local variable or instance variable before save.
40
37
  #
41
38
  # it wll check every attrasgn nodes in method define node,
42
39
  # if there are multiple attrasgn nodes who have the same subject,
43
40
  # and the subject is a local variable or an instance variable,
44
41
  # and after them, there is a call node with message :save or :save!,
45
42
  # then these attribute assignments are complex creation, should be replaced with factory method.
46
- def review_start_defn(node)
43
+ def start_defn(node)
47
44
  node.recursive_children do |child_node|
48
45
  case child_node.node_type
49
46
  when :attrasgn
@@ -1,36 +1,33 @@
1
1
  # encoding: utf-8
2
- require 'rails_best_practices/checks/check'
2
+ require 'rails_best_practices/reviews/review'
3
3
 
4
4
  module RailsBestPractices
5
- module Checks
6
- # Check a partail view file to make sure there is no instance variable.
5
+ module Reviews
6
+ # Review a partail view file to make sure there is no instance variable.
7
7
  #
8
8
  # See the best practice details here http://rails-bestpractices.com/posts/27-replace-instance-variable-with-local-variable.
9
9
  #
10
10
  # Implementation:
11
11
  #
12
- # Prepare process:
13
- # none
14
- #
15
12
  # Review process:
16
13
  # check all instance variable in partial view files,
17
14
  # if exist, then they should be replaced with local variable
18
- class ReplaceInstanceVariableWithLocalVariableCheck < Check
15
+ class ReplaceInstanceVariableWithLocalVariableReview < Review
19
16
  def url
20
17
  "http://rails-bestpractices.com/posts/27-replace-instance-variable-with-local-variable"
21
18
  end
22
19
 
23
- def interesting_review_nodes
20
+ def interesting_nodes
24
21
  [:ivar]
25
22
  end
26
23
 
27
- def interesting_review_files
24
+ def interesting_files
28
25
  PARTIAL_VIEW_FILES
29
26
  end
30
27
 
31
28
  # check ivar node in partial view file,
32
29
  # it is an instance variable, and should be replaced with local variable.
33
- def review_start_ivar(node)
30
+ def start_ivar(node)
34
31
  add_error "replace instance variable with local variable"
35
32
  end
36
33
  end
@@ -0,0 +1,92 @@
1
+ # encoding: utf-8
2
+ require 'rails_best_practices/core/check'
3
+ require 'rails_best_practices/core/error'
4
+
5
+ module RailsBestPractices
6
+ module Reviews
7
+ # A Review class that takes charge of reviewing one rails best practice.
8
+ class Review < Core::Check
9
+ attr_reader :errors
10
+
11
+ def initialize
12
+ super
13
+ @errors = []
14
+ end
15
+
16
+ # add error if source code violates rails best practice.
17
+ # error is the string message for violation of the rails best practice
18
+ # file is the filename of source code
19
+ # line is the line number of the source code which is reviewing
20
+ def add_error(error, file = @node.file, line = @node.line)
21
+ @errors << RailsBestPractices::Core::Error.new("#{file}", "#{line}", error, url)
22
+ end
23
+
24
+ # remember use count for the local or instance variable in the call or attrasgn node.
25
+ #
26
+ # find the local variable or instance variable in the call or attrasgn node,
27
+ # then save it to as key in @variable_use_count hash, and add the call count (hash value).
28
+ def remember_variable_use_count(node)
29
+ variable_node = variable(node)
30
+ if variable_node
31
+ variable_use_count[variable_node] ||= 0
32
+ variable_use_count[variable_node] += 1
33
+ end
34
+ end
35
+
36
+ # return @variable_use_count hash.
37
+ def variable_use_count
38
+ @variable_use_count ||= {}
39
+ end
40
+
41
+ # reset @variable_use_count hash.
42
+ def reset_variable_use_count
43
+ @variable_use_count = nil
44
+ end
45
+
46
+ # find local variable or instance variable in the most inner call node, e.g.
47
+ #
48
+ # if the call node is
49
+ #
50
+ # s(:call, s(:ivar, :@post), :editors, s(:arglist)),
51
+ #
52
+ # or it is
53
+ #
54
+ # s(:call,
55
+ # s(:call, s(:ivar, :@post), :editors, s(:arglist)),
56
+ # :include?,
57
+ # s(:arglist, s(:call, nil, :current_user, s(:arglist)))
58
+ # )
59
+ #
60
+ # then the variable both are s(:ivar, :@post).
61
+ #
62
+ def variable(node)
63
+ while node.subject.node_type == :call
64
+ node = node.subject
65
+ end
66
+ subject_node = node.subject
67
+ if [:ivar, :lvar].include?(subject_node.node_type) and subject_node[1] != :_erbout
68
+ subject_node
69
+ else
70
+ nil
71
+ end
72
+ end
73
+
74
+ # get the model associations from Prepares.
75
+ #
76
+ # @return [Hash]
77
+ def model_associations
78
+ @model_associations ||= Prepares.model_associations
79
+ end
80
+
81
+ # compare two sexp nodes' to_s.
82
+ #
83
+ # equal?(":test", :test) => true
84
+ # equai?("@test", :test) => true
85
+ def equal?(node, expected_node)
86
+ actual = node.to_s.downcase
87
+ expected = expected_node.to_s.downcase
88
+ actual == expected || actual == ':' + expected || actual == '@' + expected
89
+ end
90
+ end
91
+ end
92
+ end