rails_best_practices 0.6.6 → 0.6.7
Sign up to get free protection for your applications and to get access to all the features.
- 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,21 +1,18 @@
|
|
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 to use before_filter to remove duplicated first code line in different action.
|
7
7
|
#
|
8
8
|
# See the best practice detailed here http://rails-bestpractices.com/posts/22-use-before_filter.
|
9
9
|
#
|
10
10
|
# Implementation:
|
11
11
|
#
|
12
|
-
# Prepare process:
|
13
|
-
# none
|
14
|
-
#
|
15
12
|
# Review process:
|
16
13
|
# check all first code line in method definitions (actions),
|
17
14
|
# if they are duplicated, then they should be moved to before_filter.
|
18
|
-
class
|
15
|
+
class UseBeforeFilterReview < Review
|
19
16
|
|
20
17
|
PROTECTED_PRIVATE_CALLS = [[:call, nil, :protected, [:arglist]], [:call, nil, :private, [:arglist]]]
|
21
18
|
|
@@ -23,15 +20,15 @@ module RailsBestPractices
|
|
23
20
|
"http://rails-bestpractices.com/posts/22-use-before_filter"
|
24
21
|
end
|
25
22
|
|
26
|
-
def
|
23
|
+
def interesting_nodes
|
27
24
|
[:class]
|
28
25
|
end
|
29
26
|
|
30
|
-
def
|
27
|
+
def interesting_files
|
31
28
|
CONTROLLER_FILES
|
32
29
|
end
|
33
30
|
|
34
|
-
# check class define node to see if there are method define nodes whose first code line are duplicated
|
31
|
+
# check class define node to see if there are method define nodes whose first code line are duplicated.
|
35
32
|
#
|
36
33
|
# it will check every defn nodes in the class node until protected or private identification,
|
37
34
|
# if there are defn nodes who have the same first code line, like
|
@@ -74,7 +71,7 @@ module RailsBestPractices
|
|
74
71
|
# )
|
75
72
|
#
|
76
73
|
# then these duplicated first code lines should be moved to before_filter.
|
77
|
-
def
|
74
|
+
def start_class(class_node)
|
78
75
|
@first_sentences = {}
|
79
76
|
|
80
77
|
class_node.body.children.each do |child_node|
|
@@ -1,37 +1,34 @@
|
|
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 to use model association instead of foreign key id assignment.
|
7
7
|
#
|
8
8
|
# See the best practice details here http://rails-bestpractices.com/posts/2-use-model-association.
|
9
9
|
#
|
10
10
|
# Implementation:
|
11
11
|
#
|
12
|
-
# Prepare process:
|
13
|
-
# none
|
14
|
-
#
|
15
12
|
# Review process:
|
16
13
|
# check model define nodes in all controller files,
|
17
14
|
# if there is an attribute assignment node with message xxx_id=,
|
18
15
|
# and after it, there is a call node with message :save or :save!,
|
19
16
|
# and the subjects of attribute assignment node and call node are the same,
|
20
17
|
# then model association should be used instead of xxx_id assignment.
|
21
|
-
class
|
18
|
+
class UseModelAssociationReview < Review
|
22
19
|
def url
|
23
20
|
"http://rails-bestpractices.com/posts/2-use-model-association"
|
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
|
|
34
|
-
# check method define nodes to see if there are some attribute assignments that can use model association instead
|
31
|
+
# check method define nodes to see if there are some attribute assignments that can use model association instead.
|
35
32
|
#
|
36
33
|
# it will check attribute assignment node with message xxx_id=, and call node with message :save or :save!
|
37
34
|
#
|
@@ -40,7 +37,7 @@ module RailsBestPractices
|
|
40
37
|
# 2. after assignment, if there is a call node with message :save or :save!,
|
41
38
|
# and the subject of call node is one of the subject of attribute assignment node,
|
42
39
|
# then the attribute assignment should be replaced by using model association.
|
43
|
-
def
|
40
|
+
def start_defn(node)
|
44
41
|
@attrasgns = {}
|
45
42
|
node.recursive_children do |child|
|
46
43
|
case child.node_type
|
data/lib/rails_best_practices/{checks/use_observer_check.rb → reviews/use_observer_review.rb}
RENAMED
@@ -1,8 +1,8 @@
|
|
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
|
5
|
+
module Reviews
|
6
6
|
# Make sure to use observer (sorry we only check the mailer deliver now).
|
7
7
|
#
|
8
8
|
# See the best practice details here http://rails-bestpractices.com/posts/19-use-observer.
|
@@ -23,42 +23,25 @@ module RailsBestPractices
|
|
23
23
|
# if the method is a callback method,
|
24
24
|
# and there is a mailer deliver call,
|
25
25
|
# then the method should be replaced by using observer.
|
26
|
-
class
|
26
|
+
class UseObserverReview < Review
|
27
27
|
def url
|
28
28
|
"http://rails-bestpractices.com/posts/19-use-observer"
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
32
|
-
[:class]
|
33
|
-
end
|
34
|
-
|
35
|
-
def interesting_review_nodes
|
31
|
+
def interesting_nodes
|
36
32
|
[:defn, :call]
|
37
33
|
end
|
38
34
|
|
39
|
-
def
|
40
|
-
/#{MAILER_FILES}|#{MODEL_FILES}/
|
41
|
-
end
|
42
|
-
|
43
|
-
def interesting_review_files
|
35
|
+
def interesting_files
|
44
36
|
MODEL_FILES
|
45
37
|
end
|
46
38
|
|
47
39
|
def initialize
|
48
40
|
super
|
49
41
|
@callbacks = []
|
50
|
-
@mailer_names = []
|
51
42
|
end
|
52
43
|
|
53
|
-
# check
|
54
|
-
#
|
55
|
-
# if it is a subclass of ActionMailer::Base,
|
56
|
-
# then remember its class name.
|
57
|
-
def prepare_start_class(node)
|
58
|
-
remember_mailer_names(node)
|
59
|
-
end
|
60
|
-
|
61
|
-
# check a call node in review process.
|
44
|
+
# check a call node.
|
62
45
|
#
|
63
46
|
# if it is a callback definition, like
|
64
47
|
#
|
@@ -66,7 +49,7 @@ module RailsBestPractices
|
|
66
49
|
# before_destroy :send_destroy_notification
|
67
50
|
#
|
68
51
|
# then remember its callback methods (:send_create_notification).
|
69
|
-
def
|
52
|
+
def start_call(node)
|
70
53
|
remember_callback(node)
|
71
54
|
end
|
72
55
|
|
@@ -75,27 +58,13 @@ module RailsBestPractices
|
|
75
58
|
# if it is callback method,
|
76
59
|
# and there is a actionmailer deliver call in the method define node,
|
77
60
|
# then it should be replaced by using observer.
|
78
|
-
def
|
61
|
+
def start_defn(node)
|
79
62
|
if callback_method?(node) and deliver_mailer?(node)
|
80
63
|
add_error "use observer"
|
81
64
|
end
|
82
65
|
end
|
83
66
|
|
84
67
|
private
|
85
|
-
# check a class node, if its base class is ActionMailer::Base, like
|
86
|
-
#
|
87
|
-
# s(:class, :ProjectMailer,
|
88
|
-
# s(:colon2, s(:const, :ActionMailer), :Base),
|
89
|
-
# s(:scope)
|
90
|
-
# )
|
91
|
-
#
|
92
|
-
# then save the class name in @mailer_names
|
93
|
-
def remember_mailer_names(node)
|
94
|
-
if s(:colon2, s(:const, :ActionMailer), :Base) == node.base_class
|
95
|
-
@mailer_names << node.class_name.to_s
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
68
|
# check a call node, if it is a callback definition, such as after_create, before_create, like
|
100
69
|
#
|
101
70
|
# s(:call, nil, :after_create,
|
@@ -147,12 +116,16 @@ module RailsBestPractices
|
|
147
116
|
def deliver_mailer?(node)
|
148
117
|
node.grep_nodes(:node_type => :call) do |child_node|
|
149
118
|
# rails2 actionmailer deliver
|
150
|
-
return true if child_node.message.to_s =~ /^deliver_/ &&
|
119
|
+
return true if child_node.message.to_s =~ /^deliver_/ && mailer_names.include?(child_node.subject.to_s)
|
151
120
|
# rails3 actionmailer deliver
|
152
|
-
return true if :deliver == child_node.message &&
|
121
|
+
return true if :deliver == child_node.message && mailer_names.include?(child_node.subject.subject.to_s)
|
153
122
|
end
|
154
123
|
false
|
155
124
|
end
|
125
|
+
|
126
|
+
def mailer_names
|
127
|
+
@mailer_names ||= Prepares.mailer_names.collect(&:to_s)
|
128
|
+
end
|
156
129
|
end
|
157
130
|
end
|
158
131
|
end
|
@@ -1,8 +1,8 @@
|
|
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
|
5
|
+
module Reviews
|
6
6
|
# Make sure to use query attribute instead of nil?, blank? and present?.
|
7
7
|
#
|
8
8
|
# See the best practice details here http://rails-bestpractices.com/posts/56-use-query-attribute.
|
@@ -20,21 +20,19 @@ module RailsBestPractices
|
|
20
20
|
# and their messages of first call are not pluralize and not in any of the association names
|
21
21
|
# and their messages of second call are one of nil?, blank?, present?, or they are == ""
|
22
22
|
# then you can use query attribute instead.
|
23
|
-
class
|
23
|
+
class UseQueryAttributeReview < Review
|
24
24
|
|
25
25
|
QUERY_METHODS = [:nil?, :blank?, :present?]
|
26
26
|
|
27
|
-
prepare_model_associations
|
28
|
-
|
29
27
|
def url
|
30
28
|
"http://rails-bestpractices.com/posts/56-use-query-attribute"
|
31
29
|
end
|
32
30
|
|
33
|
-
def
|
31
|
+
def interesting_nodes
|
34
32
|
[:if]
|
35
33
|
end
|
36
34
|
|
37
|
-
# check if node to see whose conditional statement nodes contain nodes that can use query attribute instead
|
35
|
+
# check if node to see whose conditional statement nodes contain nodes that can use query attribute instead.
|
38
36
|
#
|
39
37
|
# it will check every call nodes in the if nodes. If the call node is
|
40
38
|
#
|
@@ -46,7 +44,7 @@ module RailsBestPractices
|
|
46
44
|
# the message is == and the argument is ""
|
47
45
|
#
|
48
46
|
# then the call node can use query attribute instead.
|
49
|
-
def
|
47
|
+
def start_if(node)
|
50
48
|
if node = query_attribute_node(node.conditional_statement)
|
51
49
|
subject_node = node.subject
|
52
50
|
add_error "use query attribute (#{subject_node.subject}.#{subject_node.message}?)", node.file, node.line
|
@@ -85,24 +83,30 @@ module RailsBestPractices
|
|
85
83
|
def possible_query_attribute?(node)
|
86
84
|
return false unless :call == node.subject.node_type
|
87
85
|
subject = node.subject.subject
|
86
|
+
return false unless subject
|
88
87
|
message = node.subject.message
|
89
88
|
|
90
|
-
[:arglist] == node.subject.arguments &&
|
91
|
-
(QUERY_METHODS.include?(node.message) || compare_with_empty_string?(node))
|
89
|
+
[:arglist] == node.subject.arguments && is_model?(subject) && !model_association?(subject, message) &&
|
90
|
+
!pluralize?(message.to_s) && (QUERY_METHODS.include?(node.message) || compare_with_empty_string?(node))
|
91
|
+
end
|
92
|
+
|
93
|
+
def is_model?(subject)
|
94
|
+
return false if :const == subject.node_type
|
95
|
+
class_name = subject.to_s(:remove_at => true).classify
|
96
|
+
!model_associations[class_name].nil?
|
92
97
|
end
|
93
98
|
|
94
|
-
# check if the subject and message is one of the model's
|
95
|
-
# the subject should match one of the class model name, and the message should
|
99
|
+
# check if the subject and message is one of the model's aassociation.
|
100
|
+
# the subject should match one of the class model name, and the message should match one of association name.
|
96
101
|
#
|
97
102
|
# subject, subject of call node, like
|
98
103
|
# s(:ivar, @user)
|
99
104
|
#
|
100
105
|
# message, message of call node, like
|
101
106
|
# :login
|
102
|
-
def
|
103
|
-
|
104
|
-
|
105
|
-
end
|
107
|
+
def model_association?(subject, message)
|
108
|
+
class_name = subject.to_s(:remove_at => true).classify
|
109
|
+
!model_associations[class_name][message.to_s].nil?
|
106
110
|
end
|
107
111
|
|
108
112
|
|
@@ -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 migration file to make sure to use say or say_with_time for customized data changes to produce a more readable output.
|
7
7
|
#
|
8
8
|
# See the best practice detials here http://rails-bestpractices.com/posts/46-use-say-and-say_with_time-in-migrations-to-make-a-useful-migration-log.
|
9
9
|
#
|
10
10
|
# Implementation:
|
11
11
|
#
|
12
|
-
# Prepare process:
|
13
|
-
# none
|
14
|
-
#
|
15
12
|
# Review process:
|
16
13
|
# check class method define nodes (self.up or self.down).
|
17
14
|
# if there is a method call in the class method definition,
|
18
15
|
# and the message of method call is not say, say_with_time and default migration methods (such as add_column and create_table),
|
19
16
|
# then the method call should be wrapped by say or say_with_time.
|
20
|
-
class
|
17
|
+
class UseSayWithTimeInMigrationsReview < Review
|
21
18
|
|
22
19
|
DEFAULT_MIGRATION_METHODS = [:add_column, :add_index, :add_timestamps, :change_column, :change_column_default, :change_table, :create_table, :drop_table, :remove_column, :remove_index, :remove_timestamps, :rename_column, :rename_index, :rename_table]
|
23
20
|
WITH_SAY_METHODS = DEFAULT_MIGRATION_METHODS + [:say, :say_with_time]
|
@@ -26,15 +23,15 @@ module RailsBestPractices
|
|
26
23
|
"http://rails-bestpractices.com/posts/46-use-say-and-say_with_time-in-migrations-to-make-a-useful-migration-log"
|
27
24
|
end
|
28
25
|
|
29
|
-
def
|
26
|
+
def interesting_nodes
|
30
27
|
[:defs]
|
31
28
|
end
|
32
29
|
|
33
|
-
def
|
30
|
+
def interesting_files
|
34
31
|
MIGRATION_FILES
|
35
32
|
end
|
36
33
|
|
37
|
-
# check a class method define node to see if there are method calls that need to be wrapped by :say or :say_with_time
|
34
|
+
# check a class method define node to see if there are method calls that need to be wrapped by :say or :say_with_time.
|
38
35
|
#
|
39
36
|
# it will check the first block node,
|
40
37
|
# if any method call whose message is not default migration methods in the block node, like
|
@@ -67,7 +64,7 @@ module RailsBestPractices
|
|
67
64
|
# )
|
68
65
|
#
|
69
66
|
# then such method call should be wrapped by say or say_with_time
|
70
|
-
def
|
67
|
+
def start_defs(node)
|
71
68
|
block_node = node.grep_node(:node_type => :block)
|
72
69
|
block_node.children.each do |child_node|
|
73
70
|
if :iter == child_node.node_type
|
@@ -1,37 +1,34 @@
|
|
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 to make sure to use scope access instead of manually checking current_user and redirect.
|
7
7
|
#
|
8
8
|
# See the best practice details here http://rails-bestpractices.com/posts/3-use-scope-access.
|
9
9
|
#
|
10
10
|
# Implementation:
|
11
11
|
#
|
12
|
-
# Prepare process:
|
13
|
-
# none
|
14
|
-
#
|
15
12
|
# Review process:
|
16
13
|
# check all if nodes to see
|
17
14
|
#
|
18
15
|
# if they are compared with current_user or current_user.id,
|
19
16
|
# and there is redirect_to method call in if block body,
|
20
17
|
# then it should be replaced by using scope access.
|
21
|
-
class
|
18
|
+
class UseScopeAccessReview < Review
|
22
19
|
def url
|
23
20
|
"http://rails-bestpractices.com/posts/3-use-scope-access"
|
24
21
|
end
|
25
22
|
|
26
|
-
def
|
23
|
+
def interesting_nodes
|
27
24
|
[:if]
|
28
25
|
end
|
29
26
|
|
30
|
-
def
|
27
|
+
def interesting_files
|
31
28
|
CONTROLLER_FILES
|
32
29
|
end
|
33
30
|
|
34
|
-
# check if node
|
31
|
+
# check if node.
|
35
32
|
#
|
36
33
|
# if it is a method call compared with current_user or current_user.id,
|
37
34
|
# and there is a redirect_to method call in the block body, like
|
@@ -42,7 +39,7 @@ module RailsBestPractices
|
|
42
39
|
# end
|
43
40
|
#
|
44
41
|
# then it should be replaced by using scope access.
|
45
|
-
def
|
42
|
+
def start_if(node)
|
46
43
|
add_error "use scope access" if current_user_redirect?(node)
|
47
44
|
end
|
48
45
|
|
@@ -21,7 +21,8 @@ Gem::Specification.new do |s|
|
|
21
21
|
s.add_dependency("i18n")
|
22
22
|
s.add_dependency("activesupport")
|
23
23
|
|
24
|
-
s.add_development_dependency("
|
24
|
+
s.add_development_dependency("rake")
|
25
|
+
s.add_development_dependency("rspec", "~> 2.4.0")
|
25
26
|
s.add_development_dependency("watchr", "~> 0.6")
|
26
27
|
s.add_development_dependency("bundler", ">= 1.0.0")
|
27
28
|
|
@@ -35,7 +36,7 @@ Gem::Specification.new do |s|
|
|
35
36
|
|
36
37
|
rails_best_practices is a code metric tool to check the quality of rails codes.
|
37
38
|
|
38
|
-
I highly recommend you
|
39
|
+
I highly recommend you browse the Rails Best Practices website first.
|
39
40
|
|
40
41
|
http://rails-bestpractices.com
|
41
42
|
|
data/rails_best_practices.yml
CHANGED
@@ -1,22 +1,22 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
1
|
+
MoveFinderToNamedScopeReview: { }
|
2
|
+
UseModelAssociationReview: { }
|
3
|
+
UseScopeAccessReview: { }
|
4
|
+
AddModelVirtualAttributeReview: { }
|
5
|
+
ReplaceComplexCreationWithFactoryMethodReview: { attribute_assignment_count: 2 }
|
6
|
+
MoveModelLogicIntoModelReview: { use_count: 4 }
|
7
|
+
OveruseRouteCustomizationsReview: { customize_count: 3 }
|
8
|
+
NeedlessDeepNestingReview: { nested_count: 2 }
|
9
|
+
NotUseDefaultRouteReview: { }
|
10
|
+
KeepFindersOnTheirOwnModelReview: { }
|
11
|
+
LawOfDemeterReview: { }
|
12
|
+
UseObserverReview: { }
|
13
|
+
IsolateSeedDataReview: { }
|
14
|
+
AlwaysAddDbIndexReview: { }
|
15
|
+
UseBeforeFilterReview: { }
|
16
|
+
MoveCodeIntoControllerReview: { }
|
17
|
+
MoveCodeIntoModelReview: { use_count: 2 }
|
18
|
+
MoveCodeIntoHelperReview: { array_count: 3 }
|
19
|
+
ReplaceInstanceVariableWithLocalVariableReview: { }
|
20
|
+
DryBundlerInCapistranoReview: { }
|
21
|
+
UseSayWithTimeInMigrationsReview: { }
|
22
|
+
UseQueryAttributeReview: { }
|