rubocop-rails 2.19.1 → 2.30.3
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 +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +70 -16
- data/config/default.yml +173 -28
- data/lib/rubocop/cop/mixin/active_record_helper.rb +16 -4
- data/lib/rubocop/cop/mixin/active_record_migrations_helper.rb +2 -2
- data/lib/rubocop/cop/mixin/database_type_resolvable.rb +66 -0
- data/lib/rubocop/cop/mixin/index_method.rb +68 -61
- data/lib/rubocop/cop/mixin/routes_helper.rb +20 -0
- data/lib/rubocop/cop/mixin/target_rails_version.rb +27 -2
- data/lib/rubocop/cop/rails/action_controller_flash_before_render.rb +3 -1
- data/lib/rubocop/cop/rails/action_controller_test_case.rb +2 -2
- data/lib/rubocop/cop/rails/action_filter.rb +3 -0
- data/lib/rubocop/cop/rails/action_order.rb +1 -5
- data/lib/rubocop/cop/rails/active_record_aliases.rb +2 -2
- data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +1 -5
- data/lib/rubocop/cop/rails/active_support_aliases.rb +6 -5
- data/lib/rubocop/cop/rails/active_support_on_load.rb +21 -1
- data/lib/rubocop/cop/rails/add_column_index.rb +1 -0
- data/lib/rubocop/cop/rails/after_commit_override.rb +1 -1
- data/lib/rubocop/cop/rails/application_record.rb +4 -0
- data/lib/rubocop/cop/rails/assert_not.rb +0 -1
- data/lib/rubocop/cop/rails/belongs_to.rb +1 -1
- data/lib/rubocop/cop/rails/blank.rb +1 -1
- data/lib/rubocop/cop/rails/bulk_change_table.rb +19 -45
- data/lib/rubocop/cop/rails/compact_blank.rb +29 -8
- data/lib/rubocop/cop/rails/content_tag.rb +2 -2
- data/lib/rubocop/cop/rails/dangerous_column_names.rb +448 -0
- data/lib/rubocop/cop/rails/date.rb +14 -5
- data/lib/rubocop/cop/rails/delegate.rb +53 -7
- data/lib/rubocop/cop/rails/duplicate_association.rb +71 -10
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +3 -3
- data/lib/rubocop/cop/rails/eager_evaluation_log_message.rb +2 -2
- data/lib/rubocop/cop/rails/enum_hash.rb +31 -8
- data/lib/rubocop/cop/rails/enum_syntax.rb +130 -0
- data/lib/rubocop/cop/rails/enum_uniqueness.rb +29 -7
- data/lib/rubocop/cop/rails/env_local.rb +69 -0
- data/lib/rubocop/cop/rails/expanded_date_range.rb +1 -1
- data/lib/rubocop/cop/rails/file_path.rb +186 -18
- data/lib/rubocop/cop/rails/find_by.rb +3 -3
- data/lib/rubocop/cop/rails/find_by_id.rb +9 -23
- data/lib/rubocop/cop/rails/find_each.rb +1 -1
- data/lib/rubocop/cop/rails/freeze_time.rb +1 -1
- data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +1 -1
- data/lib/rubocop/cop/rails/helper_instance_variable.rb +1 -1
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +7 -0
- data/lib/rubocop/cop/rails/http_status.rb +16 -5
- data/lib/rubocop/cop/rails/i18n_lazy_lookup.rb +63 -13
- data/lib/rubocop/cop/rails/i18n_locale_texts.rb +5 -1
- data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +23 -3
- data/lib/rubocop/cop/rails/index_by.rb +28 -12
- data/lib/rubocop/cop/rails/index_with.rb +28 -12
- data/lib/rubocop/cop/rails/inquiry.rb +2 -1
- data/lib/rubocop/cop/rails/inverse_of.rb +1 -1
- data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +19 -10
- data/lib/rubocop/cop/rails/link_to_blank.rb +2 -2
- data/lib/rubocop/cop/rails/match_route.rb +1 -9
- data/lib/rubocop/cop/rails/multiple_route_paths.rb +50 -0
- data/lib/rubocop/cop/rails/not_null_column.rb +100 -6
- data/lib/rubocop/cop/rails/output.rb +3 -2
- data/lib/rubocop/cop/rails/pick.rb +10 -5
- data/lib/rubocop/cop/rails/pluck.rb +21 -1
- data/lib/rubocop/cop/rails/pluck_id.rb +2 -1
- data/lib/rubocop/cop/rails/pluck_in_where.rb +35 -13
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +30 -16
- data/lib/rubocop/cop/rails/presence.rb +1 -1
- data/lib/rubocop/cop/rails/present.rb +1 -3
- data/lib/rubocop/cop/rails/rake_environment.rb +22 -6
- data/lib/rubocop/cop/rails/redundant_active_record_all_method.rb +190 -0
- data/lib/rubocop/cop/rails/redundant_foreign_key.rb +1 -1
- data/lib/rubocop/cop/rails/redundant_presence_validation_on_belongs_to.rb +16 -0
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +2 -2
- data/lib/rubocop/cop/rails/reflection_class_name.rb +2 -2
- data/lib/rubocop/cop/rails/refute_methods.rb +0 -1
- data/lib/rubocop/cop/rails/relative_date_constant.rb +1 -1
- data/lib/rubocop/cop/rails/render_plain_text.rb +6 -3
- data/lib/rubocop/cop/rails/request_referer.rb +1 -1
- data/lib/rubocop/cop/rails/response_parsed_body.rb +52 -10
- data/lib/rubocop/cop/rails/reversible_migration.rb +7 -5
- data/lib/rubocop/cop/rails/root_pathname_methods.rb +58 -15
- data/lib/rubocop/cop/rails/save_bang.rb +22 -14
- data/lib/rubocop/cop/rails/schema_comment.rb +17 -10
- data/lib/rubocop/cop/rails/select_map.rb +79 -0
- data/lib/rubocop/cop/rails/skips_model_validations.rb +9 -4
- data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +1 -2
- data/lib/rubocop/cop/rails/strip_heredoc.rb +1 -1
- data/lib/rubocop/cop/rails/strong_parameters_expect.rb +104 -0
- data/lib/rubocop/cop/rails/three_state_boolean_column.rb +4 -5
- data/lib/rubocop/cop/rails/time_zone.rb +26 -11
- data/lib/rubocop/cop/rails/transaction_exit_statement.rb +40 -9
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +11 -26
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +17 -21
- data/lib/rubocop/cop/rails/unknown_env.rb +5 -1
- data/lib/rubocop/cop/rails/unused_ignored_columns.rb +6 -0
- data/lib/rubocop/cop/rails/unused_render_content.rb +67 -0
- data/lib/rubocop/cop/rails/validation.rb +9 -4
- data/lib/rubocop/cop/rails/where_equals.rb +29 -12
- data/lib/rubocop/cop/rails/where_exists.rb +9 -9
- data/lib/rubocop/cop/rails/where_missing.rb +6 -2
- data/lib/rubocop/cop/rails/where_not.rb +18 -11
- data/lib/rubocop/cop/rails/where_range.rb +203 -0
- data/lib/rubocop/cop/rails_cops.rb +11 -0
- data/lib/rubocop/rails/migration_file_skippable.rb +54 -0
- data/lib/rubocop/rails/plugin.rb +48 -0
- data/lib/rubocop/rails/schema_loader/schema.rb +8 -7
- data/lib/rubocop/rails/schema_loader.rb +5 -15
- data/lib/rubocop/rails/version.rb +1 -1
- data/lib/rubocop/rails.rb +1 -8
- data/lib/rubocop-rails.rb +12 -4
- metadata +55 -11
- data/lib/rubocop/rails/inject.rb +0 -18
@@ -6,6 +6,9 @@ module RuboCop
|
|
6
6
|
# Identifies usages of file path joining process to use `Rails.root.join` clause.
|
7
7
|
# It is used to add uniformity when joining paths.
|
8
8
|
#
|
9
|
+
# NOTE: This cop ignores leading slashes in string literal arguments for `Rails.root.join`
|
10
|
+
# and multiple slashes in string literal arguments for `Rails.root.join` and `File.join`.
|
11
|
+
#
|
9
12
|
# @example EnforcedStyle: slashes (default)
|
10
13
|
# # bad
|
11
14
|
# Rails.root.join('app', 'models', 'goober')
|
@@ -35,6 +38,8 @@ module RuboCop
|
|
35
38
|
# Rails.root.join('app', 'models', 'goober').to_s
|
36
39
|
#
|
37
40
|
class FilePath < Base
|
41
|
+
extend AutoCorrector
|
42
|
+
|
38
43
|
include ConfigurableEnforcedStyle
|
39
44
|
include RangeHelp
|
40
45
|
|
@@ -56,61 +61,112 @@ module RuboCop
|
|
56
61
|
|
57
62
|
def on_dstr(node)
|
58
63
|
return unless rails_root_nodes?(node)
|
59
|
-
return
|
64
|
+
return if dstr_separated_by_colon?(node)
|
60
65
|
|
61
|
-
|
62
|
-
|
63
|
-
return if last_child_source.start_with?(':')
|
64
|
-
|
65
|
-
register_offense(node, require_to_s: true)
|
66
|
+
check_for_slash_after_rails_root_in_dstr(node)
|
67
|
+
check_for_extension_after_rails_root_join_in_dstr(node)
|
66
68
|
end
|
67
69
|
|
68
70
|
def on_send(node)
|
69
71
|
check_for_file_join_with_rails_root(node)
|
72
|
+
return unless node.receiver
|
73
|
+
|
70
74
|
check_for_rails_root_join_with_slash_separated_path(node)
|
71
75
|
check_for_rails_root_join_with_string_arguments(node)
|
72
76
|
end
|
73
77
|
|
74
78
|
private
|
75
79
|
|
80
|
+
def check_for_slash_after_rails_root_in_dstr(node)
|
81
|
+
rails_root_index = find_rails_root_index(node)
|
82
|
+
slash_node = node.children[rails_root_index + 1]
|
83
|
+
return unless slash_node&.str_type? && slash_node.source.start_with?(File::SEPARATOR)
|
84
|
+
return unless node.children[rails_root_index].children.first.send_type?
|
85
|
+
|
86
|
+
register_offense(node, require_to_s: false) do |corrector|
|
87
|
+
autocorrect_slash_after_rails_root_in_dstr(corrector, node, rails_root_index)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def check_for_extension_after_rails_root_join_in_dstr(node)
|
92
|
+
rails_root_index = find_rails_root_index(node)
|
93
|
+
extension_node = node.children[rails_root_index + 1]
|
94
|
+
return unless extension_node?(extension_node)
|
95
|
+
|
96
|
+
register_offense(node, require_to_s: false) do |corrector|
|
97
|
+
autocorrect_extension_after_rails_root_join_in_dstr(corrector, node, rails_root_index, extension_node)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
76
101
|
def check_for_file_join_with_rails_root(node)
|
77
102
|
return unless file_join_nodes?(node)
|
78
|
-
return unless node.arguments
|
103
|
+
return unless valid_arguments_for_file_join_with_rails_root?(node.arguments)
|
79
104
|
|
80
|
-
register_offense(node, require_to_s: true)
|
105
|
+
register_offense(node, require_to_s: true) do |corrector|
|
106
|
+
autocorrect_file_join(corrector, node) unless node.first_argument.array_type?
|
107
|
+
end
|
81
108
|
end
|
82
109
|
|
83
110
|
def check_for_rails_root_join_with_string_arguments(node)
|
84
111
|
return unless style == :slashes
|
85
112
|
return unless rails_root_nodes?(node)
|
86
113
|
return unless rails_root_join_nodes?(node)
|
87
|
-
return unless node.arguments
|
88
|
-
return unless node.arguments.all?(&:str_type?)
|
114
|
+
return unless valid_string_arguments_for_rails_root_join?(node.arguments)
|
89
115
|
|
90
|
-
register_offense(node, require_to_s: false)
|
116
|
+
register_offense(node, require_to_s: false) do |corrector|
|
117
|
+
autocorrect_rails_root_join_with_string_arguments(corrector, node)
|
118
|
+
end
|
91
119
|
end
|
92
120
|
|
93
121
|
def check_for_rails_root_join_with_slash_separated_path(node)
|
94
122
|
return unless style == :arguments
|
95
123
|
return unless rails_root_nodes?(node)
|
96
124
|
return unless rails_root_join_nodes?(node)
|
97
|
-
return unless node.arguments
|
125
|
+
return unless valid_slash_separated_path_for_rails_root_join?(node.arguments)
|
98
126
|
|
99
|
-
register_offense(node, require_to_s: false)
|
127
|
+
register_offense(node, require_to_s: false) do |corrector|
|
128
|
+
autocorrect_rails_root_join_with_slash_separated_path(corrector, node)
|
129
|
+
end
|
100
130
|
end
|
101
131
|
|
102
|
-
def
|
103
|
-
|
132
|
+
def valid_arguments_for_file_join_with_rails_root?(arguments)
|
133
|
+
return false unless arguments.any? { |arg| rails_root_nodes?(arg) }
|
134
|
+
|
135
|
+
arguments.none? { |arg| arg.variable? || arg.const_type? || string_contains_multiple_slashes?(arg) }
|
104
136
|
end
|
105
137
|
|
106
|
-
def
|
138
|
+
def valid_string_arguments_for_rails_root_join?(arguments)
|
139
|
+
return false unless arguments.size > 1
|
140
|
+
return false unless arguments.all?(&:str_type?)
|
141
|
+
|
142
|
+
arguments.none? { |arg| string_with_leading_slash?(arg) || string_contains_multiple_slashes?(arg) }
|
143
|
+
end
|
144
|
+
|
145
|
+
def valid_slash_separated_path_for_rails_root_join?(arguments)
|
146
|
+
return false unless arguments.any? { |arg| string_contains_slash?(arg) }
|
147
|
+
|
148
|
+
arguments.none? { |arg| string_with_leading_slash?(arg) || string_contains_multiple_slashes?(arg) }
|
149
|
+
end
|
150
|
+
|
151
|
+
def string_contains_slash?(node)
|
152
|
+
node.str_type? && node.value.include?(File::SEPARATOR)
|
153
|
+
end
|
154
|
+
|
155
|
+
def string_contains_multiple_slashes?(node)
|
156
|
+
node.str_type? && node.value.include?('//')
|
157
|
+
end
|
158
|
+
|
159
|
+
def string_with_leading_slash?(node)
|
160
|
+
node.str_type? && node.value.start_with?(File::SEPARATOR)
|
161
|
+
end
|
162
|
+
|
163
|
+
def register_offense(node, require_to_s:, &block)
|
107
164
|
line_range = node.loc.column...node.loc.last_column
|
108
165
|
source_range = source_range(processed_source.buffer, node.first_line, line_range)
|
109
|
-
require_to_s = false if node.dstr_type?
|
110
166
|
|
111
167
|
message = build_message(require_to_s)
|
112
168
|
|
113
|
-
add_offense(source_range, message: message)
|
169
|
+
add_offense(source_range, message: message, &block)
|
114
170
|
end
|
115
171
|
|
116
172
|
def build_message(require_to_s)
|
@@ -119,6 +175,118 @@ module RuboCop
|
|
119
175
|
|
120
176
|
format(message_template, to_s: to_s)
|
121
177
|
end
|
178
|
+
|
179
|
+
def dstr_separated_by_colon?(node)
|
180
|
+
node.children[1..].any? do |child|
|
181
|
+
child.str_type? && child.source.start_with?(':')
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def autocorrect_slash_after_rails_root_in_dstr(corrector, node, rails_root_index)
|
186
|
+
rails_root_node = node.children[rails_root_index].children.first
|
187
|
+
argument_source = extract_rails_root_join_argument_source(node, rails_root_index)
|
188
|
+
if rails_root_node.method?(:join)
|
189
|
+
append_argument(corrector, rails_root_node, argument_source)
|
190
|
+
else
|
191
|
+
replace_with_rails_root_join(corrector, rails_root_node, argument_source)
|
192
|
+
end
|
193
|
+
node.children[rails_root_index + 1..].each { |child| corrector.remove(child) }
|
194
|
+
end
|
195
|
+
|
196
|
+
def autocorrect_extension_after_rails_root_join_in_dstr(corrector, node, rails_root_index, extension_node)
|
197
|
+
rails_root_node = node.children[rails_root_index].children.first
|
198
|
+
return unless rails_root_node.last_argument.str_type?
|
199
|
+
|
200
|
+
corrector.insert_before(rails_root_node.last_argument.location.end, extension_node.source)
|
201
|
+
corrector.remove(extension_node)
|
202
|
+
end
|
203
|
+
|
204
|
+
def autocorrect_file_join(corrector, node)
|
205
|
+
replace_receiver_with_rails_root(corrector, node)
|
206
|
+
remove_first_argument_with_comma(corrector, node)
|
207
|
+
process_arguments(corrector, node.arguments)
|
208
|
+
append_to_string_conversion(corrector, node)
|
209
|
+
end
|
210
|
+
|
211
|
+
def replace_receiver_with_rails_root(corrector, node)
|
212
|
+
corrector.replace(node.receiver, 'Rails.root')
|
213
|
+
end
|
214
|
+
|
215
|
+
def remove_first_argument_with_comma(corrector, node)
|
216
|
+
corrector.remove(
|
217
|
+
range_with_surrounding_space(
|
218
|
+
range_with_surrounding_comma(
|
219
|
+
node.first_argument.source_range,
|
220
|
+
:right
|
221
|
+
),
|
222
|
+
side: :right
|
223
|
+
)
|
224
|
+
)
|
225
|
+
end
|
226
|
+
|
227
|
+
def process_arguments(corrector, arguments)
|
228
|
+
arguments.each do |argument|
|
229
|
+
if argument.str_type?
|
230
|
+
corrector.replace(argument, argument.value.delete_prefix('/').inspect)
|
231
|
+
elsif argument.array_type?
|
232
|
+
corrector.replace(argument, "*#{argument.source}")
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def append_to_string_conversion(corrector, node)
|
238
|
+
corrector.insert_after(node, '.to_s')
|
239
|
+
end
|
240
|
+
|
241
|
+
def autocorrect_rails_root_join_with_string_arguments(corrector, node)
|
242
|
+
corrector.replace(node.first_argument, %("#{node.arguments.map(&:value).join('/')}"))
|
243
|
+
node.arguments[1..].each do |argument|
|
244
|
+
corrector.remove(
|
245
|
+
range_with_surrounding_comma(
|
246
|
+
range_with_surrounding_space(
|
247
|
+
argument.source_range,
|
248
|
+
side: :left
|
249
|
+
),
|
250
|
+
:left
|
251
|
+
)
|
252
|
+
)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
def autocorrect_rails_root_join_with_slash_separated_path(corrector, node)
|
257
|
+
node.arguments.each do |argument|
|
258
|
+
next unless string_contains_slash?(argument)
|
259
|
+
|
260
|
+
index = argument.source.index(File::SEPARATOR)
|
261
|
+
rest = inner_range_of(argument).adjust(begin_pos: index - 1)
|
262
|
+
corrector.remove(rest)
|
263
|
+
corrector.insert_after(argument, %(, "#{rest.source.delete_prefix(File::SEPARATOR)}"))
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def inner_range_of(node)
|
268
|
+
node.location.end.with(begin_pos: node.location.begin.end_pos).adjust(end_pos: -1)
|
269
|
+
end
|
270
|
+
|
271
|
+
def find_rails_root_index(node)
|
272
|
+
node.children.index { |child| rails_root_nodes?(child) }
|
273
|
+
end
|
274
|
+
|
275
|
+
def append_argument(corrector, node, argument_source)
|
276
|
+
corrector.insert_after(node.last_argument, %(, "#{argument_source}"))
|
277
|
+
end
|
278
|
+
|
279
|
+
def replace_with_rails_root_join(corrector, node, argument_source)
|
280
|
+
corrector.replace(node, %<Rails.root.join("#{argument_source}")>)
|
281
|
+
end
|
282
|
+
|
283
|
+
def extract_rails_root_join_argument_source(node, rails_root_index)
|
284
|
+
node.children[rails_root_index + 1..].map(&:source).join.delete_prefix(File::SEPARATOR)
|
285
|
+
end
|
286
|
+
|
287
|
+
def extension_node?(node)
|
288
|
+
node&.str_type? && node.source.match?(/\A\.[A-Za-z]+/)
|
289
|
+
end
|
122
290
|
end
|
123
291
|
end
|
124
292
|
end
|
@@ -28,7 +28,7 @@ module RuboCop
|
|
28
28
|
include RangeHelp
|
29
29
|
extend AutoCorrector
|
30
30
|
|
31
|
-
MSG = 'Use `find_by` instead of `where
|
31
|
+
MSG = 'Use `find_by` instead of `where%<dot>s%<method>s`.'
|
32
32
|
RESTRICT_ON_SEND = %i[first take].freeze
|
33
33
|
|
34
34
|
def on_send(node)
|
@@ -37,7 +37,7 @@ module RuboCop
|
|
37
37
|
|
38
38
|
range = offense_range(node)
|
39
39
|
|
40
|
-
add_offense(range, message: format(MSG, method: node.method_name)) do |corrector|
|
40
|
+
add_offense(range, message: format(MSG, dot: node.loc.dot.source, method: node.method_name)) do |corrector|
|
41
41
|
autocorrect(corrector, node)
|
42
42
|
end
|
43
43
|
end
|
@@ -59,7 +59,7 @@ module RuboCop
|
|
59
59
|
return if node.method?(:first)
|
60
60
|
|
61
61
|
where_loc = node.receiver.loc.selector
|
62
|
-
first_loc = range_between(node.
|
62
|
+
first_loc = range_between(node.receiver.source_range.end_pos, node.loc.selector.end_pos)
|
63
63
|
|
64
64
|
corrector.replace(where_loc, 'find_by')
|
65
65
|
corrector.replace(first_loc, '')
|
@@ -24,40 +24,39 @@ module RuboCop
|
|
24
24
|
RESTRICT_ON_SEND = %i[take! find_by_id! find_by!].freeze
|
25
25
|
|
26
26
|
def_node_matcher :where_take?, <<~PATTERN
|
27
|
-
(
|
28
|
-
$(
|
27
|
+
(call
|
28
|
+
$(call _ :where
|
29
29
|
(hash
|
30
30
|
(pair (sym :id) $_))) :take!)
|
31
31
|
PATTERN
|
32
32
|
|
33
33
|
def_node_matcher :find_by?, <<~PATTERN
|
34
34
|
{
|
35
|
-
(
|
36
|
-
(
|
35
|
+
(call _ :find_by_id! $_)
|
36
|
+
(call _ :find_by! (hash (pair (sym :id) $_)))
|
37
37
|
}
|
38
38
|
PATTERN
|
39
39
|
|
40
40
|
def on_send(node)
|
41
41
|
where_take?(node) do |where, id_value|
|
42
42
|
range = where_take_offense_range(node, where)
|
43
|
-
bad_method = build_where_take_bad_method(id_value)
|
44
43
|
|
45
|
-
register_offense(range, id_value
|
44
|
+
register_offense(range, id_value)
|
46
45
|
end
|
47
46
|
|
48
47
|
find_by?(node) do |id_value|
|
49
48
|
range = find_by_offense_range(node)
|
50
|
-
bad_method = build_find_by_bad_method(node, id_value)
|
51
49
|
|
52
|
-
register_offense(range, id_value
|
50
|
+
register_offense(range, id_value)
|
53
51
|
end
|
54
52
|
end
|
53
|
+
alias on_csend on_send
|
55
54
|
|
56
55
|
private
|
57
56
|
|
58
|
-
def register_offense(range, id_value
|
57
|
+
def register_offense(range, id_value)
|
59
58
|
good_method = build_good_method(id_value)
|
60
|
-
message = format(MSG, good_method: good_method, bad_method:
|
59
|
+
message = format(MSG, good_method: good_method, bad_method: range.source)
|
61
60
|
|
62
61
|
add_offense(range, message: message) do |corrector|
|
63
62
|
corrector.replace(range, good_method)
|
@@ -75,19 +74,6 @@ module RuboCop
|
|
75
74
|
def build_good_method(id_value)
|
76
75
|
"find(#{id_value.source})"
|
77
76
|
end
|
78
|
-
|
79
|
-
def build_where_take_bad_method(id_value)
|
80
|
-
"where(id: #{id_value.source}).take!"
|
81
|
-
end
|
82
|
-
|
83
|
-
def build_find_by_bad_method(node, id_value)
|
84
|
-
case node.method_name
|
85
|
-
when :find_by_id!
|
86
|
-
"find_by_id!(#{id_value.source})"
|
87
|
-
when :find_by!
|
88
|
-
"find_by!(id: #{id_value.source})"
|
89
|
-
end
|
90
|
-
end
|
91
77
|
end
|
92
78
|
end
|
93
79
|
end
|
@@ -34,7 +34,7 @@ module RuboCop
|
|
34
34
|
RESTRICT_ON_SEND = %i[each].freeze
|
35
35
|
|
36
36
|
SCOPE_METHODS = %i[
|
37
|
-
all eager_load includes joins left_joins left_outer_joins not preload
|
37
|
+
all eager_load includes joins left_joins left_outer_joins not or preload
|
38
38
|
references unscoped where
|
39
39
|
].freeze
|
40
40
|
|
@@ -69,7 +69,7 @@ module RuboCop
|
|
69
69
|
return false unless CONVERT_METHODS.include?(method_name)
|
70
70
|
|
71
71
|
child_node, child_method_name, time_argument = *node.children
|
72
|
-
return if time_argument
|
72
|
+
return false if time_argument
|
73
73
|
|
74
74
|
current_time?(child_node, child_method_name)
|
75
75
|
end
|
@@ -6,7 +6,7 @@ module RuboCop
|
|
6
6
|
# Checks for use of the helper methods which reference
|
7
7
|
# instance variables.
|
8
8
|
#
|
9
|
-
# Relying on instance variables makes it difficult to
|
9
|
+
# Relying on instance variables makes it difficult to reuse helper
|
10
10
|
# methods.
|
11
11
|
#
|
12
12
|
# If it seems awkward to explicitly pass in each dependent
|
@@ -40,6 +40,10 @@ module RuboCop
|
|
40
40
|
(hash (kwsplat _))
|
41
41
|
PATTERN
|
42
42
|
|
43
|
+
def_node_matcher :forwarded_kwrestarg?, <<~PATTERN
|
44
|
+
(hash (forwarded-kwrestarg))
|
45
|
+
PATTERN
|
46
|
+
|
43
47
|
def_node_matcher :include_rack_test_methods?, <<~PATTERN
|
44
48
|
(send nil? :include
|
45
49
|
(const
|
@@ -83,7 +87,9 @@ module RuboCop
|
|
83
87
|
end
|
84
88
|
end
|
85
89
|
|
90
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
86
91
|
def needs_conversion?(data)
|
92
|
+
return false if data.forwarded_args_type? || forwarded_kwrestarg?(data)
|
87
93
|
return true unless data.hash_type?
|
88
94
|
return false if kwsplat_hash?(data)
|
89
95
|
|
@@ -91,6 +97,7 @@ module RuboCop
|
|
91
97
|
special_keyword_arg?(pair.key) || (format_arg?(pair.key) && data.pairs.one?)
|
92
98
|
end
|
93
99
|
end
|
100
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
94
101
|
|
95
102
|
def special_keyword_arg?(node)
|
96
103
|
node.sym_type? && KEYWORD_ARGS.include?(node.value)
|
@@ -8,10 +8,13 @@ module RuboCop
|
|
8
8
|
# @example EnforcedStyle: symbolic (default)
|
9
9
|
# # bad
|
10
10
|
# render :foo, status: 200
|
11
|
+
# render :foo, status: '200'
|
11
12
|
# render json: { foo: 'bar' }, status: 200
|
12
13
|
# render plain: 'foo/bar', status: 304
|
13
14
|
# redirect_to root_url, status: 301
|
14
15
|
# head 200
|
16
|
+
# assert_response 200
|
17
|
+
# assert_redirected_to '/some/path', status: 301
|
15
18
|
#
|
16
19
|
# # good
|
17
20
|
# render :foo, status: :ok
|
@@ -19,6 +22,8 @@ module RuboCop
|
|
19
22
|
# render plain: 'foo/bar', status: :not_modified
|
20
23
|
# redirect_to root_url, status: :moved_permanently
|
21
24
|
# head :ok
|
25
|
+
# assert_response :ok
|
26
|
+
# assert_redirected_to '/some/path', status: :moved_permanently
|
22
27
|
#
|
23
28
|
# @example EnforcedStyle: numeric
|
24
29
|
# # bad
|
@@ -27,6 +32,8 @@ module RuboCop
|
|
27
32
|
# render plain: 'foo/bar', status: :not_modified
|
28
33
|
# redirect_to root_url, status: :moved_permanently
|
29
34
|
# head :ok
|
35
|
+
# assert_response :ok
|
36
|
+
# assert_redirected_to '/some/path', status: :moved_permanently
|
30
37
|
#
|
31
38
|
# # good
|
32
39
|
# render :foo, status: 200
|
@@ -34,23 +41,27 @@ module RuboCop
|
|
34
41
|
# render plain: 'foo/bar', status: 304
|
35
42
|
# redirect_to root_url, status: 301
|
36
43
|
# head 200
|
44
|
+
# assert_response 200
|
45
|
+
# assert_redirected_to '/some/path', status: 301
|
37
46
|
#
|
38
47
|
class HttpStatus < Base
|
39
48
|
include ConfigurableEnforcedStyle
|
40
49
|
extend AutoCorrector
|
41
50
|
|
42
|
-
RESTRICT_ON_SEND = %i[render redirect_to head].freeze
|
51
|
+
RESTRICT_ON_SEND = %i[render redirect_to head assert_response assert_redirected_to].freeze
|
43
52
|
|
44
53
|
def_node_matcher :http_status, <<~PATTERN
|
45
54
|
{
|
46
55
|
(send nil? {:render :redirect_to} _ $hash)
|
47
56
|
(send nil? {:render :redirect_to} $hash)
|
48
|
-
(send nil? :head ${int sym} ...)
|
57
|
+
(send nil? {:head :assert_response} ${int sym} ...)
|
58
|
+
(send nil? :assert_redirected_to _ $hash ...)
|
59
|
+
(send nil? :assert_redirected_to $hash ...)
|
49
60
|
}
|
50
61
|
PATTERN
|
51
62
|
|
52
63
|
def_node_matcher :status_code, <<~PATTERN
|
53
|
-
(hash <(pair (sym :status) ${int sym}) ...>)
|
64
|
+
(hash <(pair (sym :status) ${int sym str}) ...>)
|
54
65
|
PATTERN
|
55
66
|
|
56
67
|
def on_send(node)
|
@@ -108,7 +119,7 @@ module RuboCop
|
|
108
119
|
private
|
109
120
|
|
110
121
|
def symbol
|
111
|
-
::Rack::Utils::SYMBOL_TO_STATUS_CODE.key(number)
|
122
|
+
::Rack::Utils::SYMBOL_TO_STATUS_CODE.key(number.to_i)
|
112
123
|
end
|
113
124
|
|
114
125
|
def number
|
@@ -133,7 +144,7 @@ module RuboCop
|
|
133
144
|
end
|
134
145
|
|
135
146
|
def offensive?
|
136
|
-
!node.int_type? && !permitted_symbol?
|
147
|
+
!node.int_type? && !permitted_symbol? && number
|
137
148
|
end
|
138
149
|
|
139
150
|
def message
|
@@ -5,7 +5,13 @@ module RuboCop
|
|
5
5
|
module Rails
|
6
6
|
# Checks for places where I18n "lazy" lookup can be used.
|
7
7
|
#
|
8
|
-
#
|
8
|
+
# This cop has two different enforcement modes. When the EnforcedStyle
|
9
|
+
# is `lazy` (the default), explicit lookups are added as offenses.
|
10
|
+
#
|
11
|
+
# When the EnforcedStyle is `explicit` then lazy lookups are added as
|
12
|
+
# offenses.
|
13
|
+
#
|
14
|
+
# @example EnforcedStyle: lazy (default)
|
9
15
|
# # en.yml
|
10
16
|
# # en:
|
11
17
|
# # books:
|
@@ -28,11 +34,29 @@ module RuboCop
|
|
28
34
|
# end
|
29
35
|
# end
|
30
36
|
#
|
37
|
+
# @example EnforcedStyle: explicit
|
38
|
+
# # bad
|
39
|
+
# class BooksController < ApplicationController
|
40
|
+
# def create
|
41
|
+
# # ...
|
42
|
+
# redirect_to books_url, notice: t('.success')
|
43
|
+
# end
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# # good
|
47
|
+
# class BooksController < ApplicationController
|
48
|
+
# def create
|
49
|
+
# # ...
|
50
|
+
# redirect_to books_url, notice: t('books.create.success')
|
51
|
+
# end
|
52
|
+
# end
|
53
|
+
#
|
31
54
|
class I18nLazyLookup < Base
|
55
|
+
include ConfigurableEnforcedStyle
|
32
56
|
include VisibilityHelp
|
33
57
|
extend AutoCorrector
|
34
58
|
|
35
|
-
MSG = 'Use
|
59
|
+
MSG = 'Use %<style>s lookup for the text used in controllers.'
|
36
60
|
|
37
61
|
RESTRICT_ON_SEND = %i[translate t].freeze
|
38
62
|
|
@@ -42,23 +66,45 @@ module RuboCop
|
|
42
66
|
|
43
67
|
def on_send(node)
|
44
68
|
translate_call?(node) do |key_node|
|
45
|
-
|
46
|
-
|
69
|
+
case style
|
70
|
+
when :lazy
|
71
|
+
handle_lazy_style(node, key_node)
|
72
|
+
when :explicit
|
73
|
+
handle_explicit_style(node, key_node)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
47
79
|
|
48
|
-
|
49
|
-
|
80
|
+
def handle_lazy_style(node, key_node)
|
81
|
+
key = key_node.value
|
82
|
+
return if key.to_s.start_with?('.')
|
50
83
|
|
51
|
-
|
52
|
-
|
84
|
+
controller, action = controller_and_action(node)
|
85
|
+
return unless controller && action
|
53
86
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
87
|
+
scoped_key = get_scoped_key(key_node, controller, action)
|
88
|
+
return unless key == scoped_key
|
89
|
+
|
90
|
+
add_offense(key_node) do |corrector|
|
91
|
+
unscoped_key = key_node.value.to_s.split('.').last
|
92
|
+
corrector.replace(key_node, "'.#{unscoped_key}'")
|
58
93
|
end
|
59
94
|
end
|
60
95
|
|
61
|
-
|
96
|
+
def handle_explicit_style(node, key_node)
|
97
|
+
key = key_node.value
|
98
|
+
return unless key.to_s.start_with?('.')
|
99
|
+
|
100
|
+
controller, action = controller_and_action(node)
|
101
|
+
return unless controller && action
|
102
|
+
|
103
|
+
scoped_key = get_scoped_key(key_node, controller, action)
|
104
|
+
add_offense(key_node) do |corrector|
|
105
|
+
corrector.replace(key_node, "'#{scoped_key}'")
|
106
|
+
end
|
107
|
+
end
|
62
108
|
|
63
109
|
def controller_and_action(node)
|
64
110
|
action_node = node.each_ancestor(:def).first
|
@@ -90,6 +136,10 @@ module RuboCop
|
|
90
136
|
|
91
137
|
path.delete_suffix('Controller').underscore
|
92
138
|
end
|
139
|
+
|
140
|
+
def message(_range)
|
141
|
+
format(MSG, style: style)
|
142
|
+
end
|
93
143
|
end
|
94
144
|
end
|
95
145
|
end
|
@@ -80,7 +80,11 @@ module RuboCop
|
|
80
80
|
PATTERN
|
81
81
|
|
82
82
|
def_node_matcher :flash_assignment?, <<~PATTERN
|
83
|
-
(send
|
83
|
+
(send
|
84
|
+
{
|
85
|
+
(send nil? :flash)
|
86
|
+
(send (send nil? :flash) :now)
|
87
|
+
} :[]= _ $str)
|
84
88
|
PATTERN
|
85
89
|
|
86
90
|
def_node_search :mail_subject, <<~PATTERN
|