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.
- data/Gemfile +0 -1
- data/README.md +28 -24
- data/Rakefile +0 -8
- data/install_supported_rubies.sh +2 -3
- data/lib/rails_best_practices.rb +8 -7
- data/lib/rails_best_practices/core.rb +1 -0
- data/lib/rails_best_practices/core/check.rb +68 -0
- data/lib/rails_best_practices/core/checking_visitor.rb +18 -15
- data/lib/rails_best_practices/core/runner.rb +22 -12
- data/lib/rails_best_practices/core/visitable_sexp.rb +6 -2
- data/lib/rails_best_practices/prepares.rb +11 -0
- data/lib/rails_best_practices/prepares/mailer_prepare.rb +33 -0
- data/lib/rails_best_practices/prepares/model_prepare.rb +60 -0
- data/lib/rails_best_practices/reviews.rb +23 -0
- data/lib/rails_best_practices/{checks/add_model_virtual_attribute_check.rb → reviews/add_model_virtual_attribute_review.rb} +6 -9
- data/lib/rails_best_practices/{checks/always_add_db_index_check.rb → reviews/always_add_db_index_review.rb} +9 -12
- data/lib/rails_best_practices/{checks/dry_bundler_in_capistrano_check.rb → reviews/dry_bundler_in_capistrano_review.rb} +8 -11
- data/lib/rails_best_practices/{checks/isolate_seed_data_check.rb → reviews/isolate_seed_data_review.rb} +11 -14
- 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
- data/lib/rails_best_practices/{checks/law_of_demeter_check.rb → reviews/law_of_demeter_review.rb} +10 -14
- data/lib/rails_best_practices/{checks/move_code_into_controller_check.rb → reviews/move_code_into_controller_review.rb} +8 -11
- data/lib/rails_best_practices/{checks/move_code_into_helper_check.rb → reviews/move_code_into_helper_review.rb} +7 -10
- data/lib/rails_best_practices/{checks/move_code_into_model_check.rb → reviews/move_code_into_model_review.rb} +7 -10
- data/lib/rails_best_practices/{checks/move_finder_to_named_scope_check.rb → reviews/move_finder_to_named_scope_review.rb} +7 -10
- data/lib/rails_best_practices/{checks/move_model_logic_into_model_check.rb → reviews/move_model_logic_into_model_review.rb} +8 -11
- data/lib/rails_best_practices/{checks/needless_deep_nesting_check.rb → reviews/needless_deep_nesting_review.rb} +8 -11
- data/lib/rails_best_practices/{checks/not_use_default_route_check.rb → reviews/not_use_default_route_review.rb} +7 -10
- data/lib/rails_best_practices/{checks/overuse_route_customizations_check.rb → reviews/overuse_route_customizations_review.rb} +10 -13
- 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
- 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
- data/lib/rails_best_practices/reviews/review.rb +92 -0
- data/lib/rails_best_practices/{checks/use_before_filter_check.rb → reviews/use_before_filter_review.rb} +8 -11
- data/lib/rails_best_practices/{checks/use_model_association_check.rb → reviews/use_model_association_review.rb} +8 -11
- data/lib/rails_best_practices/{checks/use_observer_check.rb → reviews/use_observer_review.rb} +14 -41
- data/lib/rails_best_practices/{checks/use_query_attribute_check.rb → reviews/use_query_attribute_review.rb} +20 -16
- 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
- data/lib/rails_best_practices/{checks/use_scope_access_check.rb → reviews/use_scope_access_review.rb} +8 -11
- data/lib/rails_best_practices/version.rb +1 -1
- data/rails_best_practices.gemspec +3 -2
- data/rails_best_practices.yml +22 -22
- data/rake_rubies.sh +3 -2
- data/spec/rails_best_practices/core/check_spec.rb +41 -0
- data/spec/rails_best_practices/core/checking_visitor_spec.rb +78 -0
- data/spec/rails_best_practices/core/visitable_sexp_spec.rb +39 -36
- data/spec/rails_best_practices/prepares/mailer_prepare_spec.rb +14 -0
- data/spec/rails_best_practices/prepares/model_prepare_spec.rb +22 -0
- data/spec/rails_best_practices/{checks/add_model_virtual_attribute_check_spec.rb → reviews/add_model_virtual_attribute_review_spec.rb} +17 -25
- data/spec/rails_best_practices/{checks/always_add_db_index_check_spec.rb → reviews/always_add_db_index_review_spec.rb} +28 -41
- data/spec/rails_best_practices/{checks/dry_bundler_in_capistrano_check_spec.rb → reviews/dry_bundler_in_capistrano_review_spec.rb} +7 -11
- data/spec/rails_best_practices/{checks/isolate_seed_data_check_spec.rb → reviews/isolate_seed_data_review_spec.rb} +13 -20
- 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
- data/spec/rails_best_practices/{checks/law_of_demeter_check_spec.rb → reviews/law_of_demeter_review_spec.rb} +24 -26
- data/spec/rails_best_practices/reviews/move_code_into_controller_review_spec.rb +29 -0
- data/spec/rails_best_practices/reviews/move_code_into_helper_review_spec.rb +24 -0
- data/spec/rails_best_practices/{checks/move_code_into_model_check_spec.rb → reviews/move_code_into_model_review_spec.rb} +12 -18
- 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
- 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
- data/spec/rails_best_practices/{checks/needless_deep_nesting_check_spec.rb → reviews/needless_deep_nesting_review_spec.rb} +26 -37
- data/spec/rails_best_practices/{checks/not_use_default_route_check_spec.rb → reviews/not_use_default_route_review_spec.rb} +13 -19
- data/spec/rails_best_practices/{checks/overuse_route_customizations_check_spec.rb → reviews/overuse_route_customizations_review_spec.rb} +27 -39
- 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
- data/spec/rails_best_practices/reviews/replace_instance_variable_with_local_variable_review_spec.rb +31 -0
- data/spec/rails_best_practices/reviews/review_spec.rb +11 -0
- data/spec/rails_best_practices/{checks/use_before_filter_check_spec.rb → reviews/use_before_filter_review_spec.rb} +11 -17
- data/spec/rails_best_practices/{checks/use_model_association_check_spec.rb → reviews/use_model_association_review_spec.rb} +12 -18
- data/spec/rails_best_practices/{checks/use_observer_check_spec.rb → reviews/use_observer_review_spec.rb} +28 -29
- data/spec/rails_best_practices/reviews/use_query_attribute_review_spec.rb +190 -0
- 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
- data/spec/rails_best_practices/{checks/use_scope_access_check_spec.rb → reviews/use_scope_access_review_spec.rb} +28 -37
- data/spec/rails_best_practices_spec.rb +4 -4
- data/spec/spec_helper.rb +1 -0
- metadata +128 -102
- data/lib/rails_best_practices/checks.rb +0 -23
- data/lib/rails_best_practices/checks/check.rb +0 -203
- data/spec/rails_best_practices/checks/check_spec.rb +0 -57
- data/spec/rails_best_practices/checks/move_code_into_controller_check_spec.rb +0 -33
- data/spec/rails_best_practices/checks/move_code_into_helper_check_spec.rb +0 -28
- data/spec/rails_best_practices/checks/replace_instance_variable_with_local_variable_check_spec.rb +0 -36
- 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/
|
2
|
+
require 'rails_best_practices/reviews/review'
|
3
3
|
|
4
4
|
module RailsBestPractices
|
5
|
-
module
|
6
|
-
#
|
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
|
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
|
21
|
+
def interesting_nodes
|
25
22
|
[:if]
|
26
23
|
end
|
27
24
|
|
28
|
-
def
|
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
|
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/
|
2
|
+
require 'rails_best_practices/reviews/review'
|
3
3
|
|
4
4
|
module RailsBestPractices
|
5
|
-
module
|
6
|
-
#
|
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
|
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
|
25
|
+
def interesting_nodes
|
29
26
|
[:call]
|
30
27
|
end
|
31
28
|
|
32
|
-
def
|
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
|
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/
|
2
|
+
require 'rails_best_practices/reviews/review'
|
3
3
|
|
4
4
|
module RailsBestPractices
|
5
|
-
module
|
6
|
-
#
|
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
|
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
|
22
|
+
def interesting_nodes
|
26
23
|
[:defn]
|
27
24
|
end
|
28
25
|
|
29
|
-
def
|
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
|
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
|
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/
|
2
|
+
require 'rails_best_practices/reviews/review'
|
3
3
|
|
4
4
|
module RailsBestPractices
|
5
|
-
module
|
6
|
-
#
|
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
|
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
|
34
|
+
def interesting_nodes
|
38
35
|
[:call, :iter]
|
39
36
|
end
|
40
37
|
|
41
|
-
def
|
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
|
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
|
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/
|
2
|
+
require 'rails_best_practices/reviews/review'
|
3
3
|
|
4
4
|
module RailsBestPractices
|
5
|
-
module
|
6
|
-
#
|
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
|
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
|
26
|
+
def interesting_nodes
|
30
27
|
[:call]
|
31
28
|
end
|
32
29
|
|
33
|
-
def
|
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
|
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/
|
2
|
+
require 'rails_best_practices/reviews/review'
|
3
3
|
|
4
4
|
module RailsBestPractices
|
5
|
-
module
|
6
|
-
#
|
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
|
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
|
38
|
+
def interesting_nodes
|
42
39
|
[:call, :iter]
|
43
40
|
end
|
44
41
|
|
45
|
-
def
|
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
|
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
|
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
|
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
|
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/
|
2
|
+
require 'rails_best_practices/reviews/review'
|
3
3
|
|
4
4
|
module RailsBestPractices
|
5
|
-
module
|
6
|
-
#
|
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
|
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
|
23
|
+
def interesting_nodes
|
27
24
|
[:defn]
|
28
25
|
end
|
29
26
|
|
30
|
-
def
|
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
|
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
|
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/
|
2
|
+
require 'rails_best_practices/reviews/review'
|
3
3
|
|
4
4
|
module RailsBestPractices
|
5
|
-
module
|
6
|
-
#
|
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
|
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
|
20
|
+
def interesting_nodes
|
24
21
|
[:ivar]
|
25
22
|
end
|
26
23
|
|
27
|
-
def
|
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
|
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
|