rails_best_practices 1.19.2 → 1.20.1
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.
- checksums.yaml +5 -5
- data/.gitignore +0 -1
- data/.travis.yml +2 -3
- data/CHANGELOG.md +7 -7
- data/Gemfile +3 -5
- data/Gemfile.lock +125 -0
- data/Guardfile +2 -0
- data/README.md +6 -6
- data/Rakefile +2 -17
- data/assets/result.html.erb +2 -0
- data/lib/rails_best_practices.rb +3 -2
- data/lib/rails_best_practices/analyzer.rb +61 -49
- data/lib/rails_best_practices/cli.rb +22 -0
- data/lib/rails_best_practices/command.rb +1 -131
- data/lib/rails_best_practices/core/check.rb +64 -56
- data/lib/rails_best_practices/core/checks_loader.rb +24 -23
- data/lib/rails_best_practices/core/configs.rb +1 -2
- data/lib/rails_best_practices/core/controllers.rb +1 -2
- data/lib/rails_best_practices/core/error.rb +1 -1
- data/lib/rails_best_practices/core/helpers.rb +1 -2
- data/lib/rails_best_practices/core/mailers.rb +1 -2
- data/lib/rails_best_practices/core/methods.rb +27 -21
- data/lib/rails_best_practices/core/model_associations.rb +10 -5
- data/lib/rails_best_practices/core/models.rb +1 -2
- data/lib/rails_best_practices/core/modules.rb +1 -1
- data/lib/rails_best_practices/core/routes.rb +2 -2
- data/lib/rails_best_practices/core/runner.rb +67 -73
- data/lib/rails_best_practices/lexicals/long_line_check.rb +7 -3
- data/lib/rails_best_practices/option_parser.rb +156 -0
- data/lib/rails_best_practices/prepares.rb +1 -1
- data/lib/rails_best_practices/prepares/controller_prepare.rb +24 -17
- data/lib/rails_best_practices/prepares/gemfile_prepare.rb +2 -2
- data/lib/rails_best_practices/prepares/helper_prepare.rb +6 -1
- data/lib/rails_best_practices/prepares/initializer_prepare.rb +3 -3
- data/lib/rails_best_practices/prepares/mailer_prepare.rb +2 -1
- data/lib/rails_best_practices/prepares/model_prepare.rb +63 -23
- data/lib/rails_best_practices/prepares/route_prepare.rb +28 -21
- data/lib/rails_best_practices/prepares/schema_prepare.rb +1 -1
- data/lib/rails_best_practices/reviews/add_model_virtual_attribute_review.rb +38 -34
- data/lib/rails_best_practices/reviews/always_add_db_index_review.rb +94 -89
- data/lib/rails_best_practices/reviews/check_destroy_return_value_review.rb +15 -5
- data/lib/rails_best_practices/reviews/check_save_return_value_review.rb +20 -8
- data/lib/rails_best_practices/reviews/default_scope_is_evil_review.rb +1 -1
- data/lib/rails_best_practices/reviews/dry_bundler_in_capistrano_review.rb +1 -1
- data/lib/rails_best_practices/reviews/hash_syntax_review.rb +16 -16
- data/lib/rails_best_practices/reviews/isolate_seed_data_review.rb +12 -12
- data/lib/rails_best_practices/reviews/keep_finders_on_their_own_model_review.rb +10 -11
- data/lib/rails_best_practices/reviews/law_of_demeter_review.rb +25 -24
- data/lib/rails_best_practices/reviews/move_code_into_controller_review.rb +4 -4
- data/lib/rails_best_practices/reviews/move_code_into_helper_review.rb +9 -10
- data/lib/rails_best_practices/reviews/move_finder_to_named_scope_review.rb +10 -11
- data/lib/rails_best_practices/reviews/needless_deep_nesting_review.rb +24 -22
- data/lib/rails_best_practices/reviews/not_rescue_exception_review.rb +1 -1
- data/lib/rails_best_practices/reviews/not_use_default_route_review.rb +1 -2
- data/lib/rails_best_practices/reviews/not_use_time_ago_in_words_review.rb +1 -1
- data/lib/rails_best_practices/reviews/overuse_route_customizations_review.rb +8 -8
- data/lib/rails_best_practices/reviews/protect_mass_assignment_review.rb +35 -32
- data/lib/rails_best_practices/reviews/remove_empty_helpers_review.rb +4 -4
- data/lib/rails_best_practices/reviews/remove_unused_methods_in_controllers_review.rb +26 -19
- data/lib/rails_best_practices/reviews/remove_unused_methods_in_helpers_review.rb +12 -10
- data/lib/rails_best_practices/reviews/remove_unused_methods_in_models_review.rb +38 -18
- data/lib/rails_best_practices/reviews/replace_complex_creation_with_factory_method_review.rb +11 -11
- data/lib/rails_best_practices/reviews/restrict_auto_generated_routes_review.rb +77 -74
- data/lib/rails_best_practices/reviews/review.rb +2 -1
- data/lib/rails_best_practices/reviews/simplify_render_in_controllers_review.rb +2 -3
- data/lib/rails_best_practices/reviews/simplify_render_in_views_review.rb +12 -12
- data/lib/rails_best_practices/reviews/use_before_filter_review.rb +18 -15
- data/lib/rails_best_practices/reviews/use_model_association_review.rb +15 -15
- data/lib/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review.rb +24 -22
- data/lib/rails_best_practices/reviews/use_observer_review.rb +28 -28
- data/lib/rails_best_practices/reviews/use_parentheses_in_method_def_review.rb +6 -6
- data/lib/rails_best_practices/reviews/use_query_attribute_review.rb +68 -66
- data/lib/rails_best_practices/reviews/use_say_with_time_in_migrations_review.rb +9 -8
- data/lib/rails_best_practices/reviews/use_scope_access_review.rb +16 -14
- data/lib/rails_best_practices/reviews/use_turbo_sprockets_rails3_review.rb +2 -1
- data/lib/rails_best_practices/version.rb +1 -1
- data/rails_best_practices.gemspec +38 -43
- data/spec/fixtures/lib/rails_best_practices/plugins/reviews/not_use_rails_root_review.rb +1 -2
- data/spec/rails_best_practices/analyzer_spec.rb +73 -42
- data/spec/rails_best_practices/core/check_spec.rb +5 -5
- data/spec/rails_best_practices/core/checks_loader_spec.rb +3 -3
- data/spec/rails_best_practices/core/configs_spec.rb +1 -1
- data/spec/rails_best_practices/core/controllers_spec.rb +1 -1
- data/spec/rails_best_practices/core/error_spec.rb +21 -18
- data/spec/rails_best_practices/core/except_methods_spec.rb +7 -7
- data/spec/rails_best_practices/core/gems_spec.rb +4 -4
- data/spec/rails_best_practices/core/helpers_spec.rb +1 -1
- data/spec/rails_best_practices/core/klasses_spec.rb +3 -3
- data/spec/rails_best_practices/core/mailers_spec.rb +1 -1
- data/spec/rails_best_practices/core/methods_spec.rb +6 -6
- data/spec/rails_best_practices/core/model_associations_spec.rb +10 -6
- data/spec/rails_best_practices/core/model_attributes_spec.rb +4 -4
- data/spec/rails_best_practices/core/models_spec.rb +1 -1
- data/spec/rails_best_practices/core/modules_spec.rb +5 -5
- data/spec/rails_best_practices/core/routes_spec.rb +5 -5
- data/spec/rails_best_practices/core/runner_spec.rb +9 -7
- data/spec/rails_best_practices/core_ext/erubis_spec.rb +10 -10
- data/spec/rails_best_practices/lexicals/long_line_check_spec.rb +32 -31
- data/spec/rails_best_practices/lexicals/remove_tab_check_spec.rb +6 -6
- data/spec/rails_best_practices/lexicals/remove_trailing_whitespace_check_spec.rb +6 -6
- data/spec/rails_best_practices/prepares/config_prepare_spec.rb +2 -2
- data/spec/rails_best_practices/prepares/controller_prepare_spec.rb +18 -10
- data/spec/rails_best_practices/prepares/gemfile_prepare_spec.rb +17 -17
- data/spec/rails_best_practices/prepares/helper_prepare_spec.rb +3 -3
- data/spec/rails_best_practices/prepares/initializer_prepare_spec.rb +3 -3
- data/spec/rails_best_practices/prepares/mailer_prepare_spec.rb +2 -2
- data/spec/rails_best_practices/prepares/model_prepare_spec.rb +79 -43
- data/spec/rails_best_practices/prepares/route_prepare_spec.rb +141 -76
- data/spec/rails_best_practices/prepares/schema_prepare_spec.rb +2 -2
- data/spec/rails_best_practices/reviews/add_model_virtual_attribute_review_spec.rb +18 -12
- data/spec/rails_best_practices/reviews/always_add_db_index_review_spec.rb +28 -22
- data/spec/rails_best_practices/reviews/check_destroy_return_value_review_spec.rb +15 -13
- data/spec/rails_best_practices/reviews/check_save_return_value_review_spec.rb +31 -21
- data/spec/rails_best_practices/reviews/default_scope_is_evil_review_spec.rb +6 -6
- data/spec/rails_best_practices/reviews/dry_bundler_in_capistrano_review_spec.rb +5 -5
- data/spec/rails_best_practices/reviews/hash_syntax_review_spec.rb +13 -13
- data/spec/rails_best_practices/reviews/isolate_seed_data_review_spec.rb +7 -7
- data/spec/rails_best_practices/reviews/keep_finders_on_their_own_model_review_spec.rb +9 -9
- data/spec/rails_best_practices/reviews/law_of_demeter_review_spec.rb +29 -22
- data/spec/rails_best_practices/reviews/move_code_into_controller_review_spec.rb +6 -6
- data/spec/rails_best_practices/reviews/move_code_into_helper_review_spec.rb +11 -6
- data/spec/rails_best_practices/reviews/move_code_into_model_review_spec.rb +32 -22
- data/spec/rails_best_practices/reviews/move_finder_to_named_scope_review_spec.rb +7 -7
- data/spec/rails_best_practices/reviews/move_model_logic_into_model_review_spec.rb +9 -7
- data/spec/rails_best_practices/reviews/needless_deep_nesting_review_spec.rb +9 -9
- data/spec/rails_best_practices/reviews/not_rescue_exception_review_spec.rb +9 -9
- data/spec/rails_best_practices/reviews/not_use_default_route_review_spec.rb +5 -5
- data/spec/rails_best_practices/reviews/not_use_time_ago_in_words_review_spec.rb +7 -7
- data/spec/rails_best_practices/reviews/overuse_route_customizations_review_spec.rb +7 -7
- data/spec/rails_best_practices/reviews/protect_mass_assignment_review_spec.rb +24 -17
- data/spec/rails_best_practices/reviews/remove_empty_helpers_review_spec.rb +6 -6
- data/spec/rails_best_practices/reviews/remove_unused_methods_in_controllers_review_spec.rb +64 -31
- data/spec/rails_best_practices/reviews/remove_unused_methods_in_helpers_review_spec.rb +21 -14
- data/spec/rails_best_practices/reviews/remove_unused_methods_in_models_review_spec.rb +57 -53
- data/spec/rails_best_practices/reviews/replace_complex_creation_with_factory_method_review_spec.rb +10 -8
- data/spec/rails_best_practices/reviews/replace_instance_variable_with_local_variable_review_spec.rb +20 -14
- data/spec/rails_best_practices/reviews/restrict_auto_generated_routes_review_spec.rb +54 -31
- data/spec/rails_best_practices/reviews/simplify_render_in_controllers_review_spec.rb +9 -9
- data/spec/rails_best_practices/reviews/simplify_render_in_views_review_spec.rb +13 -13
- data/spec/rails_best_practices/reviews/use_before_filter_review_spec.rb +11 -9
- data/spec/rails_best_practices/reviews/use_model_association_review_spec.rb +7 -7
- data/spec/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review_spec.rb +35 -31
- data/spec/rails_best_practices/reviews/use_observer_review_spec.rb +6 -6
- data/spec/rails_best_practices/reviews/use_parentheses_in_method_def_review_spec.rb +10 -8
- data/spec/rails_best_practices/reviews/use_query_attribute_review_spec.rb +31 -24
- data/spec/rails_best_practices/reviews/use_say_with_time_in_migrations_review_spec.rb +15 -11
- data/spec/rails_best_practices/reviews/use_scope_access_review_spec.rb +14 -14
- data/spec/rails_best_practices/reviews/use_turbo_sprockets_rails3_review_spec.rb +61 -59
- metadata +16 -18
@@ -20,27 +20,29 @@ module RailsBestPractices
|
|
20
20
|
def initialize(options = {})
|
21
21
|
super
|
22
22
|
@helper_methods = Prepares.helper_methods
|
23
|
-
self.class.interesting_files Prepares.helpers.map(&:descendants)
|
23
|
+
self.class.interesting_files *Prepares.helpers.map(&:descendants)
|
24
24
|
end
|
25
25
|
|
26
26
|
# get all unused methods at the end of review process
|
27
27
|
add_callback :after_check do
|
28
28
|
@helper_methods.get_all_unused_methods.each do |method|
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
next if excepted?(method)
|
30
|
+
|
31
|
+
add_error "remove unused methods (#{method.class_name}##{method.method_name})",
|
32
|
+
method.file,
|
33
|
+
method.line_number
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
35
37
|
protected
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
39
|
+
def methods
|
40
|
+
@helper_methods
|
41
|
+
end
|
40
42
|
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
def internal_except_methods
|
44
|
+
['*#url_for']
|
45
|
+
end
|
44
46
|
end
|
45
47
|
end
|
46
48
|
end
|
@@ -80,30 +80,50 @@ module RailsBestPractices
|
|
80
80
|
# get all unused methods at the end of review process.
|
81
81
|
add_callback :after_check do
|
82
82
|
@model_methods.get_all_unused_methods.each do |method|
|
83
|
-
|
84
|
-
|
85
|
-
|
83
|
+
next unless !excepted?(method) && method.method_name !~ /=$/
|
84
|
+
|
85
|
+
add_error "remove unused methods (#{method.class_name}##{method.method_name})",
|
86
|
+
method.file,
|
87
|
+
method.line_number
|
86
88
|
end
|
87
89
|
end
|
88
90
|
|
89
91
|
protected
|
90
92
|
|
91
|
-
|
92
|
-
|
93
|
-
|
93
|
+
def methods
|
94
|
+
@model_methods
|
95
|
+
end
|
94
96
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
97
|
+
def internal_except_methods
|
98
|
+
%w[
|
99
|
+
initialize
|
100
|
+
validate
|
101
|
+
validate_each
|
102
|
+
validate_on_create
|
103
|
+
validate_on_update
|
104
|
+
human_attribute_name
|
105
|
+
assign_attributes
|
106
|
+
attributes
|
107
|
+
attribute
|
108
|
+
to_xml
|
109
|
+
to_json
|
110
|
+
as_json
|
111
|
+
to_param
|
112
|
+
before_save
|
113
|
+
before_create
|
114
|
+
before_update
|
115
|
+
before_destroy
|
116
|
+
after_save
|
117
|
+
after_create
|
118
|
+
after_update
|
119
|
+
after_destroy
|
120
|
+
after_find
|
121
|
+
after_initialize
|
122
|
+
method_missing
|
123
|
+
table_name
|
124
|
+
module_prefix
|
125
|
+
].map { |method_name| "*\##{method_name}" }
|
126
|
+
end
|
107
127
|
end
|
108
128
|
end
|
109
129
|
end
|
data/lib/rails_best_practices/reviews/replace_complex_creation_with_factory_method_review.rb
CHANGED
@@ -37,7 +37,7 @@ module RailsBestPractices
|
|
37
37
|
node.recursive_children do |child_node|
|
38
38
|
case child_node.sexp_type
|
39
39
|
when :assign
|
40
|
-
if
|
40
|
+
if child_node.receiver[2].to_s == '.'
|
41
41
|
remember_variable_use_count(child_node)
|
42
42
|
end
|
43
43
|
when :call
|
@@ -49,18 +49,18 @@ module RailsBestPractices
|
|
49
49
|
|
50
50
|
private
|
51
51
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
end
|
52
|
+
# check the call node to see if it is with message "save" or "save!",
|
53
|
+
# and the count attribute assignment on the receiver of the call node is greater than @assign_count defined,
|
54
|
+
# then it is a complex creation, should be replaced with factory method.
|
55
|
+
def check_variable_save(node)
|
56
|
+
if ['save', 'save!'].include? node.message.to_s
|
57
|
+
variable = node.receiver.to_s
|
58
|
+
if variable_use_count[variable].to_i > @assigns_count
|
59
|
+
hint = "#{variable} attribute_assignment_count > #{@assigns_count}"
|
60
|
+
add_error "replace complex creation with factory method (#{hint})"
|
62
61
|
end
|
63
62
|
end
|
63
|
+
end
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
@@ -38,23 +38,23 @@ module RailsBestPractices
|
|
38
38
|
|
39
39
|
# check if the generated routes have the corresponding actions in controller for rails routes.
|
40
40
|
add_callback :start_command, :start_command_call do |node|
|
41
|
-
if
|
41
|
+
if node.message.to_s == 'resources'
|
42
42
|
if (mod = module_option(node))
|
43
43
|
@namespaces << mod
|
44
44
|
end
|
45
45
|
check_resources(node)
|
46
46
|
@resource_controllers << node.arguments.all.first.to_s
|
47
|
-
elsif
|
47
|
+
elsif node.message.to_s == 'resource'
|
48
48
|
check_resource(node)
|
49
49
|
@resource_controllers << node.arguments.all.first.to_s
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
53
|
add_callback :end_command do |node|
|
54
|
-
if
|
54
|
+
if node.message.to_s == 'resources'
|
55
55
|
@resource_controllers.pop
|
56
56
|
@namespaces.pop if module_option(node)
|
57
|
-
elsif
|
57
|
+
elsif node.message.to_s == 'resource'
|
58
58
|
@resource_controllers.pop
|
59
59
|
end
|
60
60
|
end
|
@@ -90,103 +90,106 @@ module RailsBestPractices
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def check_method_add_block?(node)
|
93
|
-
|
93
|
+
node[1].sexp_type == :command || (node[1].sexp_type == :command_call && node.receiver.to_s != 'map')
|
94
94
|
end
|
95
95
|
|
96
96
|
private
|
97
97
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
98
|
+
# check resources call, if the routes generated by resources does not exist in the controller.
|
99
|
+
def check_resources(node)
|
100
|
+
_check(node, resources_methods)
|
101
|
+
end
|
102
102
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
103
|
+
# check resource call, if the routes generated by resources does not exist in the controller.
|
104
|
+
def check_resource(node)
|
105
|
+
_check(node, resource_methods)
|
106
|
+
end
|
107
107
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
108
|
+
# get the controller name.
|
109
|
+
def controller_name(node)
|
110
|
+
if option_with_hash(node)
|
111
|
+
option_node = node.arguments.all[1]
|
112
|
+
name =
|
112
113
|
if hash_key_exist?(option_node, 'controller')
|
113
|
-
|
114
|
+
option_node.hash_value('controller').to_s
|
114
115
|
else
|
115
|
-
|
116
|
+
node.arguments.all.first.to_s.gsub('::', '').tableize
|
116
117
|
end
|
117
|
-
|
118
|
-
|
119
|
-
end
|
120
|
-
namespaced_class_name(name)
|
118
|
+
else
|
119
|
+
name = node.arguments.all.first.to_s.gsub('::', '').tableize
|
121
120
|
end
|
121
|
+
namespaced_class_name(name)
|
122
|
+
end
|
122
123
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
end
|
124
|
+
# get the class name with namespace.
|
125
|
+
def namespaced_class_name(name)
|
126
|
+
class_name = "#{name.split('/').map(&:camelize).join('::')}Controller"
|
127
|
+
if @namespaces.empty?
|
128
|
+
class_name
|
129
|
+
else
|
130
|
+
@namespaces.map { |namespace| "#{namespace.camelize}::" }.join('') + class_name
|
131
131
|
end
|
132
|
+
end
|
132
133
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
134
|
+
def _check(node, methods)
|
135
|
+
controller_name = controller_name(node)
|
136
|
+
return unless Prepares.controllers.include? controller_name
|
137
|
+
|
138
|
+
_methods = _methods(node, methods)
|
139
|
+
unless _methods.all? { |meth| Prepares.controller_methods.has_method?(controller_name, meth) }
|
140
|
+
prepared_method_names = Prepares.controller_methods.get_methods(controller_name).map(&:method_name)
|
141
|
+
only_methods = (_methods & prepared_method_names).map { |meth| ":#{meth}" }
|
142
|
+
routes_message =
|
143
|
+
if only_methods.size > 3
|
144
|
+
"except: [#{(methods.map { |meth| ':' + meth } - only_methods).join(', ')}]"
|
145
|
+
else
|
146
|
+
"only: [#{only_methods.join(', ')}]"
|
147
|
+
end
|
148
|
+
add_error "restrict auto-generated routes #{friendly_route_name(node)} (#{routes_message})"
|
147
149
|
end
|
150
|
+
end
|
148
151
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
else
|
158
|
-
(methods - Array(option_node.hash_value('except').to_object))
|
159
|
-
end
|
152
|
+
def _methods(node, methods)
|
153
|
+
if option_with_hash(node)
|
154
|
+
option_node = node.arguments.all[1]
|
155
|
+
if hash_key_exist?(option_node, 'only')
|
156
|
+
option_node.hash_value('only').to_s == 'none' ? [] : Array(option_node.hash_value('only').to_object)
|
157
|
+
elsif hash_key_exist?(option_node, 'except')
|
158
|
+
if option_node.hash_value('except').to_s == 'all'
|
159
|
+
[]
|
160
160
|
else
|
161
|
-
methods
|
161
|
+
(methods - Array(option_node.hash_value('except').to_object))
|
162
162
|
end
|
163
163
|
else
|
164
164
|
methods
|
165
165
|
end
|
166
|
+
else
|
167
|
+
methods
|
166
168
|
end
|
169
|
+
end
|
167
170
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
end
|
171
|
+
def module_option(node)
|
172
|
+
option_node = node.arguments[1].last
|
173
|
+
if option_node && option_node.sexp_type == :bare_assoc_hash && hash_key_exist?(option_node, 'module')
|
174
|
+
option_node.hash_value('module').to_s
|
173
175
|
end
|
176
|
+
end
|
174
177
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
+
def option_with_hash(node)
|
179
|
+
node.arguments.all.size > 1 && node.arguments.all[1].sexp_type == :bare_assoc_hash
|
180
|
+
end
|
178
181
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
+
def hash_key_exist?(node, key)
|
183
|
+
node.hash_keys&.include?(key)
|
184
|
+
end
|
182
185
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
end
|
186
|
+
def friendly_route_name(node)
|
187
|
+
if @resource_controllers.last == node.arguments.to_s
|
188
|
+
[@namespaces.join('/'), @resource_controllers.join('/')].delete_if(&:blank?).join('/')
|
189
|
+
else
|
190
|
+
[@namespaces.join('/'), @resource_controllers.join('/'), node.arguments.to_s].delete_if(&:blank?).join('/')
|
189
191
|
end
|
192
|
+
end
|
190
193
|
end
|
191
194
|
end
|
192
195
|
end
|
@@ -13,7 +13,7 @@ module RailsBestPractices
|
|
13
13
|
# then save it to as key in @variable_use_count hash, and add the call count (hash value).
|
14
14
|
def remember_variable_use_count(node)
|
15
15
|
variable_node = variable(node)
|
16
|
-
if variable_node && 'self'
|
16
|
+
if variable_node && variable_node.to_s != 'self' && @last_variable_node != variable_node
|
17
17
|
@last_variable_node = variable_node
|
18
18
|
variable_use_count[variable_node.to_s] ||= 0
|
19
19
|
variable_use_count[variable_node.to_s] += 1
|
@@ -36,6 +36,7 @@ module RailsBestPractices
|
|
36
36
|
node = node.receiver
|
37
37
|
end
|
38
38
|
return if %i[fcall hash].include?(node.receiver.sexp_type)
|
39
|
+
|
39
40
|
node.receiver
|
40
41
|
end
|
41
42
|
|
@@ -21,10 +21,9 @@ module RailsBestPractices
|
|
21
21
|
# if its message is render and the arguments contain a key action, template or file,
|
22
22
|
# then it should be replaced by simplified syntax.
|
23
23
|
add_callback :start_command do |node|
|
24
|
-
if
|
24
|
+
if node.message.to_s == 'render'
|
25
25
|
keys = node.arguments.all.first.hash_keys
|
26
|
-
if keys && keys.size == 1 &&
|
27
|
-
(keys.include?('action') || keys.include?('template') || keys.include?('file'))
|
26
|
+
if keys && keys.size == 1 && (keys.include?('action') || keys.include?('template') || keys.include?('file'))
|
28
27
|
add_error 'simplify render in controllers'
|
29
28
|
end
|
30
29
|
end
|
@@ -22,10 +22,10 @@ module RailsBestPractices
|
|
22
22
|
# if its message is render and the arguments contain a key partial,
|
23
23
|
# then it should be replaced by simplified syntax.
|
24
24
|
add_callback :start_command do |node|
|
25
|
-
if
|
26
|
-
hash_node =
|
27
|
-
if hash_node && :bare_assoc_hash
|
28
|
-
|
25
|
+
if node.message.to_s == 'render'
|
26
|
+
hash_node = node.arguments.all.first
|
27
|
+
if hash_node && hash_node.sexp_type == :bare_assoc_hash && include_partial?(hash_node) &&
|
28
|
+
valid_hash?(hash_node)
|
29
29
|
add_error 'simplify render in views'
|
30
30
|
end
|
31
31
|
end
|
@@ -33,15 +33,15 @@ module RailsBestPractices
|
|
33
33
|
|
34
34
|
protected
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
def include_partial?(hash_node)
|
37
|
+
hash_node.hash_keys.include?('partial') && !hash_node.hash_value('partial').to_s.include?('/')
|
38
|
+
end
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
def valid_hash?(hash_node)
|
41
|
+
keys = hash_node.hash_keys
|
42
|
+
keys.delete('partial')
|
43
|
+
(keys - VALID_KEYS).empty?
|
44
|
+
end
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
@@ -12,6 +12,7 @@ module RailsBestPractices
|
|
12
12
|
# Review process:
|
13
13
|
# check all first code line_number in method definitions (actions),
|
14
14
|
# if they are duplicated, then they should be moved to before_filter.
|
15
|
+
|
15
16
|
class UseBeforeFilterReview < Review
|
16
17
|
interesting_nodes :class
|
17
18
|
interesting_files CONTROLLER_FILES
|
@@ -34,29 +35,31 @@ module RailsBestPractices
|
|
34
35
|
var_ref_or_vcall_included = %i[var_ref vcall].include?(statement_node.sexp_type)
|
35
36
|
private_or_protected_included = %w[protected private].include?(statement_node.to_s)
|
36
37
|
break if var_ref_or_vcall_included && private_or_protected_included
|
37
|
-
|
38
|
+
|
39
|
+
remember_first_sentence(statement_node) if statement_node.sexp_type == :def
|
38
40
|
end
|
39
41
|
@first_sentences.each do |_first_sentence, def_nodes|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
next unless def_nodes.size > @customize_count
|
43
|
+
|
44
|
+
add_error "use before_filter for #{def_nodes.map { |node| node.method_name.to_s }.join(',')}",
|
45
|
+
node.file,
|
46
|
+
def_nodes.map(&:line_number).join(',')
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
48
50
|
private
|
49
51
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
52
|
+
# check method define node, and remember the first sentence.
|
53
|
+
def remember_first_sentence(node)
|
54
|
+
first_sentence = node.body.statements.first
|
55
|
+
return unless first_sentence
|
56
|
+
|
57
|
+
first_sentence = first_sentence.remove_line_and_column
|
58
|
+
unless first_sentence == s(:nil)
|
59
|
+
@first_sentences[first_sentence] ||= []
|
60
|
+
@first_sentences[first_sentence] << node
|
59
61
|
end
|
62
|
+
end
|
60
63
|
end
|
61
64
|
end
|
62
65
|
end
|