rubocop-rails 2.7.0 → 2.9.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 +4 -4
- data/README.md +16 -0
- data/config/default.yml +78 -4
- data/lib/rubocop/cop/mixin/active_record_helper.rb +5 -3
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +40 -0
- data/lib/rubocop/cop/mixin/index_method.rb +25 -11
- data/lib/rubocop/cop/rails/action_filter.rb +10 -14
- data/lib/rubocop/cop/rails/active_record_aliases.rb +13 -17
- data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +19 -16
- data/lib/rubocop/cop/rails/active_record_override.rb +1 -1
- data/lib/rubocop/cop/rails/active_support_aliases.rb +12 -21
- data/lib/rubocop/cop/rails/after_commit_override.rb +91 -0
- data/lib/rubocop/cop/rails/application_controller.rb +3 -7
- data/lib/rubocop/cop/rails/application_job.rb +2 -1
- data/lib/rubocop/cop/rails/application_mailer.rb +2 -7
- data/lib/rubocop/cop/rails/application_record.rb +2 -7
- data/lib/rubocop/cop/rails/arel_star.rb +41 -0
- data/lib/rubocop/cop/rails/assert_not.rb +8 -10
- data/lib/rubocop/cop/rails/attribute_default_block_value.rb +90 -0
- data/lib/rubocop/cop/rails/belongs_to.rb +9 -18
- data/lib/rubocop/cop/rails/blank.rb +27 -27
- data/lib/rubocop/cop/rails/bulk_change_table.rb +1 -1
- data/lib/rubocop/cop/rails/content_tag.rb +17 -17
- data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +2 -1
- data/lib/rubocop/cop/rails/date.rb +10 -11
- data/lib/rubocop/cop/rails/default_scope.rb +11 -4
- data/lib/rubocop/cop/rails/delegate.rb +9 -9
- data/lib/rubocop/cop/rails/delegate_allow_blank.rb +7 -8
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +13 -11
- data/lib/rubocop/cop/rails/enum_hash.rb +11 -10
- data/lib/rubocop/cop/rails/enum_uniqueness.rb +2 -1
- data/lib/rubocop/cop/rails/environment_comparison.rb +18 -14
- data/lib/rubocop/cop/rails/exit.rb +4 -10
- data/lib/rubocop/cop/rails/file_path.rb +5 -4
- data/lib/rubocop/cop/rails/find_by.rb +13 -13
- data/lib/rubocop/cop/rails/find_by_id.rb +12 -21
- data/lib/rubocop/cop/rails/find_each.rb +17 -18
- data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +3 -2
- data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +4 -7
- data/lib/rubocop/cop/rails/helper_instance_variable.rb +30 -2
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +25 -21
- data/lib/rubocop/cop/rails/http_status.rb +7 -9
- data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +8 -6
- data/lib/rubocop/cop/rails/index_by.rb +11 -2
- data/lib/rubocop/cop/rails/index_with.rb +11 -2
- data/lib/rubocop/cop/rails/inquiry.rb +7 -2
- data/lib/rubocop/cop/rails/inverse_of.rb +3 -2
- data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +17 -15
- data/lib/rubocop/cop/rails/link_to_blank.rb +20 -22
- data/lib/rubocop/cop/rails/mailer_name.rb +19 -13
- data/lib/rubocop/cop/rails/match_route.rb +16 -13
- data/lib/rubocop/cop/rails/negate_include.rb +10 -8
- data/lib/rubocop/cop/rails/not_null_column.rb +2 -1
- data/lib/rubocop/cop/rails/order_by_id.rb +52 -0
- data/lib/rubocop/cop/rails/output.rb +5 -2
- data/lib/rubocop/cop/rails/output_safety.rb +3 -2
- data/lib/rubocop/cop/rails/pick.rb +14 -12
- data/lib/rubocop/cop/rails/pluck.rb +6 -9
- data/lib/rubocop/cop/rails/pluck_id.rb +4 -6
- data/lib/rubocop/cop/rails/pluck_in_where.rb +39 -5
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +10 -14
- data/lib/rubocop/cop/rails/presence.rb +12 -13
- data/lib/rubocop/cop/rails/present.rb +30 -24
- data/lib/rubocop/cop/rails/rake_environment.rb +9 -11
- data/lib/rubocop/cop/rails/read_write_attribute.rb +12 -11
- data/lib/rubocop/cop/rails/redundant_allow_nil.rb +29 -31
- data/lib/rubocop/cop/rails/redundant_foreign_key.rb +9 -12
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +11 -10
- data/lib/rubocop/cop/rails/reflection_class_name.rb +4 -3
- data/lib/rubocop/cop/rails/refute_methods.rb +9 -10
- data/lib/rubocop/cop/rails/relative_date_constant.rb +20 -9
- data/lib/rubocop/cop/rails/render_inline.rb +5 -12
- data/lib/rubocop/cop/rails/render_plain_text.rb +9 -14
- data/lib/rubocop/cop/rails/request_referer.rb +7 -7
- data/lib/rubocop/cop/rails/reversible_migration.rb +82 -7
- data/lib/rubocop/cop/rails/safe_navigation.rb +11 -10
- data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +5 -10
- data/lib/rubocop/cop/rails/save_bang.rb +19 -22
- data/lib/rubocop/cop/rails/scope_args.rb +2 -1
- data/lib/rubocop/cop/rails/short_i18n.rb +7 -9
- data/lib/rubocop/cop/rails/skips_model_validations.rb +4 -4
- data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +82 -0
- data/lib/rubocop/cop/rails/time_zone.rb +22 -20
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +6 -6
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +18 -8
- data/lib/rubocop/cop/rails/unknown_env.rb +15 -4
- data/lib/rubocop/cop/rails/validation.rb +15 -14
- data/lib/rubocop/cop/rails/where_equals.rb +98 -0
- data/lib/rubocop/cop/rails/where_exists.rb +74 -16
- data/lib/rubocop/cop/rails/where_not.rb +97 -0
- data/lib/rubocop/cop/rails_cops.rb +8 -0
- data/lib/rubocop/rails/schema_loader.rb +4 -4
- data/lib/rubocop/rails/schema_loader/schema.rb +5 -5
- data/lib/rubocop/rails/version.rb +5 -1
- metadata +23 -9
@@ -19,11 +19,13 @@ module RuboCop
|
|
19
19
|
#
|
20
20
|
# # good
|
21
21
|
# request.referrer
|
22
|
-
class RequestReferer <
|
22
|
+
class RequestReferer < Base
|
23
23
|
include ConfigurableEnforcedStyle
|
24
|
+
extend AutoCorrector
|
24
25
|
|
25
26
|
MSG = 'Use `request.%<prefer>s` instead of ' \
|
26
27
|
'`request.%<current>s`.'
|
28
|
+
RESTRICT_ON_SEND = %i[referer referrer].freeze
|
27
29
|
|
28
30
|
def_node_matcher :referer?, <<~PATTERN
|
29
31
|
(send (send nil? :request) {:referer :referrer})
|
@@ -33,17 +35,15 @@ module RuboCop
|
|
33
35
|
referer?(node) do
|
34
36
|
return unless node.method?(wrong_method_name)
|
35
37
|
|
36
|
-
add_offense(node.source_range
|
38
|
+
add_offense(node.source_range) do |corrector|
|
39
|
+
corrector.replace(node, "request.#{style}")
|
40
|
+
end
|
37
41
|
end
|
38
42
|
end
|
39
43
|
|
40
|
-
def autocorrect(node)
|
41
|
-
->(corrector) { corrector.replace(node, "request.#{style}") }
|
42
|
-
end
|
43
|
-
|
44
44
|
private
|
45
45
|
|
46
|
-
def message(
|
46
|
+
def message(_range)
|
47
47
|
format(MSG, prefer: style, current: wrong_method_name)
|
48
48
|
end
|
49
49
|
|
@@ -129,8 +129,53 @@ module RuboCop
|
|
129
129
|
# end
|
130
130
|
# end
|
131
131
|
#
|
132
|
+
# @example
|
133
|
+
# # remove_columns
|
134
|
+
#
|
135
|
+
# # bad
|
136
|
+
# def change
|
137
|
+
# remove_columns :users, :name, :email
|
138
|
+
# end
|
139
|
+
#
|
140
|
+
# # good
|
141
|
+
# def change
|
142
|
+
# reversible do |dir|
|
143
|
+
# dir.up do
|
144
|
+
# remove_columns :users, :name, :email
|
145
|
+
# end
|
146
|
+
#
|
147
|
+
# dir.down do
|
148
|
+
# add_column :users, :name, :string
|
149
|
+
# add_column :users, :email, :string
|
150
|
+
# end
|
151
|
+
# end
|
152
|
+
# end
|
153
|
+
#
|
154
|
+
# # good (Rails >= 6.1, see https://github.com/rails/rails/pull/36589)
|
155
|
+
# def change
|
156
|
+
# remove_columns :users, :name, :email, type: :string
|
157
|
+
# end
|
158
|
+
#
|
159
|
+
# @example
|
160
|
+
# # remove_index
|
161
|
+
#
|
162
|
+
# # bad
|
163
|
+
# def change
|
164
|
+
# remove_index :users, name: :index_users_on_email
|
165
|
+
# end
|
166
|
+
#
|
167
|
+
# # good
|
168
|
+
# def change
|
169
|
+
# remove_index :users, :email
|
170
|
+
# end
|
171
|
+
#
|
172
|
+
# # good
|
173
|
+
# def change
|
174
|
+
# remove_index :users, column: :email
|
175
|
+
# end
|
176
|
+
#
|
132
177
|
# @see https://api.rubyonrails.org/classes/ActiveRecord/Migration/CommandRecorder.html
|
133
|
-
class ReversibleMigration <
|
178
|
+
class ReversibleMigration < Base
|
134
179
|
MSG = '%<action>s is not reversible.'
|
135
180
|
|
136
181
|
def_node_matcher :irreversible_schema_statement_call, <<~PATTERN
|
@@ -153,6 +198,14 @@ module RuboCop
|
|
153
198
|
(send nil? :change_table $_ ...)
|
154
199
|
PATTERN
|
155
200
|
|
201
|
+
def_node_matcher :remove_columns_call, <<~PATTERN
|
202
|
+
(send nil? :remove_columns ... $_)
|
203
|
+
PATTERN
|
204
|
+
|
205
|
+
def_node_matcher :remove_index_call, <<~PATTERN
|
206
|
+
(send nil? :remove_index _ $_)
|
207
|
+
PATTERN
|
208
|
+
|
156
209
|
def on_send(node)
|
157
210
|
return unless within_change_method?(node)
|
158
211
|
return if within_reversible_or_up_only_block?(node)
|
@@ -162,6 +215,8 @@ module RuboCop
|
|
162
215
|
check_reversible_hash_node(node)
|
163
216
|
check_remove_column_node(node)
|
164
217
|
check_remove_foreign_key_node(node)
|
218
|
+
check_remove_columns_node(node)
|
219
|
+
check_remove_index_node(node)
|
165
220
|
end
|
166
221
|
|
167
222
|
def on_block(node)
|
@@ -216,11 +271,7 @@ module RuboCop
|
|
216
271
|
def check_remove_foreign_key_node(node)
|
217
272
|
remove_foreign_key_call(node) do |arg|
|
218
273
|
if arg.hash_type? && !all_hash_key?(arg, :to_table)
|
219
|
-
add_offense(
|
220
|
-
node,
|
221
|
-
message: format(MSG,
|
222
|
-
action: 'remove_foreign_key(without table)')
|
223
|
-
)
|
274
|
+
add_offense(node, message: format(MSG, action: 'remove_foreign_key(without table)'))
|
224
275
|
end
|
225
276
|
end
|
226
277
|
end
|
@@ -237,6 +288,30 @@ module RuboCop
|
|
237
288
|
end
|
238
289
|
end
|
239
290
|
|
291
|
+
def check_remove_columns_node(node)
|
292
|
+
remove_columns_call(node) do |args|
|
293
|
+
unless all_hash_key?(args, :type) && target_rails_version >= 6.1
|
294
|
+
action = target_rails_version >= 6.1 ? 'remove_columns(without type)' : 'remove_columns'
|
295
|
+
|
296
|
+
add_offense(
|
297
|
+
node,
|
298
|
+
message: format(MSG, action: action)
|
299
|
+
)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
def check_remove_index_node(node)
|
305
|
+
remove_index_call(node) do |args|
|
306
|
+
if args.hash_type? && !all_hash_key?(args, :column)
|
307
|
+
add_offense(
|
308
|
+
node,
|
309
|
+
message: format(MSG, action: 'remove_index(without column)')
|
310
|
+
)
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
240
315
|
def check_change_table_offense(receiver, node)
|
241
316
|
method_name = node.method_name
|
242
317
|
return if receiver != node.receiver &&
|
@@ -281,7 +356,7 @@ module RuboCop
|
|
281
356
|
key.children.first.to_sym
|
282
357
|
end
|
283
358
|
|
284
|
-
hash_keys & keys == keys
|
359
|
+
(hash_keys & keys).sort == keys
|
285
360
|
end
|
286
361
|
end
|
287
362
|
end
|
@@ -36,10 +36,12 @@ module RuboCop
|
|
36
36
|
# foo&.bar
|
37
37
|
# foo&.bar(baz)
|
38
38
|
# foo&.bar { |e| e.baz }
|
39
|
-
class SafeNavigation <
|
39
|
+
class SafeNavigation < Base
|
40
40
|
include RangeHelp
|
41
|
+
extend AutoCorrector
|
41
42
|
|
42
43
|
MSG = 'Use safe navigation (`&.`) instead of `%<try>s`.'
|
44
|
+
RESTRICT_ON_SEND = %i[try try!].freeze
|
43
45
|
|
44
46
|
def_node_matcher :try_call, <<~PATTERN
|
45
47
|
(send !nil? ${:try :try!} $_ ...)
|
@@ -50,24 +52,23 @@ module RuboCop
|
|
50
52
|
return if try_method == :try && !cop_config['ConvertTry']
|
51
53
|
return unless dispatch.sym_type? && dispatch.value.match?(/\w+[=!?]?/)
|
52
54
|
|
53
|
-
add_offense(node, message: format(MSG, try: try_method))
|
55
|
+
add_offense(node, message: format(MSG, try: try_method)) do |corrector|
|
56
|
+
autocorrect(corrector, node)
|
57
|
+
end
|
54
58
|
end
|
55
59
|
end
|
56
60
|
|
57
|
-
|
61
|
+
private
|
62
|
+
|
63
|
+
def autocorrect(corrector, node)
|
58
64
|
method_node, *params = *node.arguments
|
59
65
|
method = method_node.source[1..-1]
|
60
66
|
|
61
|
-
range = range_between(node.loc.dot.begin_pos,
|
62
|
-
node.loc.expression.end_pos)
|
67
|
+
range = range_between(node.loc.dot.begin_pos, node.loc.expression.end_pos)
|
63
68
|
|
64
|
-
|
65
|
-
corrector.replace(range, replacement(method, params))
|
66
|
-
end
|
69
|
+
corrector.replace(range, replacement(method, params))
|
67
70
|
end
|
68
71
|
|
69
|
-
private
|
70
|
-
|
71
72
|
def replacement(method, params)
|
72
73
|
new_params = params.map(&:source).join(', ')
|
73
74
|
|
@@ -19,7 +19,9 @@ module RuboCop
|
|
19
19
|
# do_something if foo.blank?
|
20
20
|
# do_something unless foo.blank?
|
21
21
|
#
|
22
|
-
class SafeNavigationWithBlank <
|
22
|
+
class SafeNavigationWithBlank < Base
|
23
|
+
extend AutoCorrector
|
24
|
+
|
23
25
|
MSG =
|
24
26
|
'Avoid calling `blank?` with the safe navigation operator ' \
|
25
27
|
'in conditionals.'
|
@@ -31,15 +33,8 @@ module RuboCop
|
|
31
33
|
def on_if(node)
|
32
34
|
return unless safe_navigation_blank_in_conditional?(node)
|
33
35
|
|
34
|
-
add_offense(node)
|
35
|
-
|
36
|
-
|
37
|
-
def autocorrect(node)
|
38
|
-
lambda do |corrector|
|
39
|
-
corrector.replace(
|
40
|
-
safe_navigation_blank_in_conditional?(node).location.dot,
|
41
|
-
'.'
|
42
|
-
)
|
36
|
+
add_offense(node) do |corrector|
|
37
|
+
corrector.replace(safe_navigation_blank_in_conditional?(node).location.dot, '.')
|
43
38
|
end
|
44
39
|
end
|
45
40
|
end
|
@@ -98,8 +98,9 @@ module RuboCop
|
|
98
98
|
# Services::Service::Mailer.update(message: 'Message')
|
99
99
|
# Service::Mailer::update
|
100
100
|
#
|
101
|
-
class SaveBang <
|
101
|
+
class SaveBang < Base
|
102
102
|
include NegativeConditional
|
103
|
+
extend AutoCorrector
|
103
104
|
|
104
105
|
MSG = 'Use `%<prefer>s` instead of `%<current>s` if the return ' \
|
105
106
|
'value is not checked.'
|
@@ -113,11 +114,10 @@ module RuboCop
|
|
113
114
|
first_or_create find_or_create_by].freeze
|
114
115
|
MODIFY_PERSIST_METHODS = %i[save
|
115
116
|
update update_attributes destroy].freeze
|
116
|
-
|
117
|
-
MODIFY_PERSIST_METHODS).freeze
|
117
|
+
RESTRICT_ON_SEND = (CREATE_PERSIST_METHODS + MODIFY_PERSIST_METHODS).freeze
|
118
118
|
|
119
|
-
def
|
120
|
-
|
119
|
+
def self.joining_forces
|
120
|
+
VariableForce
|
121
121
|
end
|
122
122
|
|
123
123
|
def after_leaving_scope(scope, _variable_table)
|
@@ -135,10 +135,10 @@ module RuboCop
|
|
135
135
|
return unless persist_method?(node, CREATE_PERSIST_METHODS)
|
136
136
|
return if persisted_referenced?(assignment)
|
137
137
|
|
138
|
-
|
138
|
+
register_offense(node, CREATE_MSG)
|
139
139
|
end
|
140
140
|
|
141
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
141
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
142
142
|
def on_send(node)
|
143
143
|
return unless persist_method?(node)
|
144
144
|
return if return_value_assigned?(node)
|
@@ -148,25 +148,22 @@ module RuboCop
|
|
148
148
|
return if explicit_return?(node)
|
149
149
|
return if checked_immediately?(node)
|
150
150
|
|
151
|
-
|
151
|
+
register_offense(node, MSG)
|
152
152
|
end
|
153
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
153
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
154
154
|
alias on_csend on_send
|
155
155
|
|
156
|
-
def autocorrect(node)
|
157
|
-
save_loc = node.loc.selector
|
158
|
-
new_method = "#{node.method_name}!"
|
159
|
-
|
160
|
-
->(corrector) { corrector.replace(save_loc, new_method) }
|
161
|
-
end
|
162
|
-
|
163
156
|
private
|
164
157
|
|
165
|
-
def
|
166
|
-
|
167
|
-
|
158
|
+
def register_offense(node, msg)
|
159
|
+
current_method = node.method_name
|
160
|
+
bang_method = "#{current_method}!"
|
161
|
+
full_message = format(msg, prefer: bang_method, current: current_method)
|
168
162
|
|
169
|
-
|
163
|
+
range = node.loc.selector
|
164
|
+
add_offense(range, message: full_message) do |corrector|
|
165
|
+
corrector.replace(range, bang_method)
|
166
|
+
end
|
170
167
|
end
|
171
168
|
|
172
169
|
def right_assignment_node(assignment)
|
@@ -218,7 +215,7 @@ module RuboCop
|
|
218
215
|
def check_used_in_condition_or_compound_boolean(node)
|
219
216
|
return false unless in_condition_or_compound_boolean?(node)
|
220
217
|
|
221
|
-
|
218
|
+
register_offense(node, CREATE_CONDITIONAL_MSG) unless MODIFY_PERSIST_METHODS.include?(node.method_name)
|
222
219
|
|
223
220
|
true
|
224
221
|
end
|
@@ -318,7 +315,7 @@ module RuboCop
|
|
318
315
|
assignment&.lvasgn_type?
|
319
316
|
end
|
320
317
|
|
321
|
-
def persist_method?(node, methods =
|
318
|
+
def persist_method?(node, methods = RESTRICT_ON_SEND)
|
322
319
|
methods.include?(node.method_name) &&
|
323
320
|
expected_signature?(node) &&
|
324
321
|
!allowed_receiver?(node)
|
@@ -13,8 +13,9 @@ module RuboCop
|
|
13
13
|
#
|
14
14
|
# # good
|
15
15
|
# scope :something, -> { where(something: true) }
|
16
|
-
class ScopeArgs <
|
16
|
+
class ScopeArgs < Base
|
17
17
|
MSG = 'Use `lambda`/`proc` instead of a plain method call.'
|
18
|
+
RESTRICT_ON_SEND = %i[scope].freeze
|
18
19
|
|
19
20
|
def_node_matcher :scope?, '(send nil? :scope _ $send)'
|
20
21
|
|
@@ -38,8 +38,9 @@ module RuboCop
|
|
38
38
|
# t :key
|
39
39
|
# l Time.now
|
40
40
|
#
|
41
|
-
class ShortI18n <
|
41
|
+
class ShortI18n < Base
|
42
42
|
include ConfigurableEnforcedStyle
|
43
|
+
extend AutoCorrector
|
43
44
|
|
44
45
|
MSG = 'Use `%<good_method>s` instead of `%<bad_method>s`.'
|
45
46
|
|
@@ -48,6 +49,8 @@ module RuboCop
|
|
48
49
|
localize: :l
|
49
50
|
}.freeze
|
50
51
|
|
52
|
+
RESTRICT_ON_SEND = PREFERRED_METHODS.keys.freeze
|
53
|
+
|
51
54
|
def_node_matcher :long_i18n?, <<~PATTERN
|
52
55
|
(send {nil? (const nil? :I18n)} ${:translate :localize} ...)
|
53
56
|
PATTERN
|
@@ -58,15 +61,10 @@ module RuboCop
|
|
58
61
|
long_i18n?(node) do |method_name|
|
59
62
|
good_method = PREFERRED_METHODS[method_name]
|
60
63
|
message = format(MSG, good_method: good_method, bad_method: method_name)
|
64
|
+
range = node.loc.selector
|
61
65
|
|
62
|
-
add_offense(
|
63
|
-
|
64
|
-
end
|
65
|
-
|
66
|
-
def autocorrect(node)
|
67
|
-
long_i18n?(node) do |method_name|
|
68
|
-
lambda do |corrector|
|
69
|
-
corrector.replace(node.loc.selector, PREFERRED_METHODS[method_name])
|
66
|
+
add_offense(range, message: message) do |corrector|
|
67
|
+
corrector.replace(range, PREFERRED_METHODS[method_name])
|
70
68
|
end
|
71
69
|
end
|
72
70
|
end
|
@@ -7,7 +7,7 @@ module RuboCop
|
|
7
7
|
# validations which are listed in
|
8
8
|
# https://guides.rubyonrails.org/active_record_validations.html#skipping-validations
|
9
9
|
#
|
10
|
-
# Methods may be ignored from this rule by configuring a `
|
10
|
+
# Methods may be ignored from this rule by configuring a `AllowedMethods`.
|
11
11
|
#
|
12
12
|
# @example
|
13
13
|
# # bad
|
@@ -26,7 +26,7 @@ module RuboCop
|
|
26
26
|
# user.update(website: 'example.com')
|
27
27
|
# FileUtils.touch('file')
|
28
28
|
#
|
29
|
-
# @example
|
29
|
+
# @example AllowedMethods: ["touch"]
|
30
30
|
# # bad
|
31
31
|
# DiscussionBoard.decrement_counter(:post_count, 5)
|
32
32
|
# DiscussionBoard.increment_counter(:post_count, 5)
|
@@ -35,7 +35,7 @@ module RuboCop
|
|
35
35
|
# # good
|
36
36
|
# user.touch
|
37
37
|
#
|
38
|
-
class SkipsModelValidations <
|
38
|
+
class SkipsModelValidations < Base
|
39
39
|
MSG = 'Avoid using `%<method>s` because it skips validations.'
|
40
40
|
|
41
41
|
METHODS_WITH_ARGUMENTS = %w[decrement!
|
@@ -76,7 +76,7 @@ module RuboCop
|
|
76
76
|
return if good_touch?(node)
|
77
77
|
return if good_insert?(node)
|
78
78
|
|
79
|
-
add_offense(node,
|
79
|
+
add_offense(node.loc.selector, message: message(node))
|
80
80
|
end
|
81
81
|
alias on_csend on_send
|
82
82
|
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
#
|
7
|
+
# Checks SQL heredocs to use `.squish`.
|
8
|
+
# Some SQL syntax (e.g. PostgreSQL comments and functions) requires newlines
|
9
|
+
# to be preserved in order to work, thus auto-correction for this cop is not safe.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# # bad
|
13
|
+
# <<-SQL
|
14
|
+
# SELECT * FROM posts;
|
15
|
+
# SQL
|
16
|
+
#
|
17
|
+
# <<-SQL
|
18
|
+
# SELECT * FROM posts
|
19
|
+
# WHERE id = 1
|
20
|
+
# SQL
|
21
|
+
#
|
22
|
+
# execute(<<~SQL, "Post Load")
|
23
|
+
# SELECT * FROM posts
|
24
|
+
# WHERE post_id = 1
|
25
|
+
# SQL
|
26
|
+
#
|
27
|
+
# # good
|
28
|
+
# <<-SQL.squish
|
29
|
+
# SELECT * FROM posts;
|
30
|
+
# SQL
|
31
|
+
#
|
32
|
+
# <<~SQL.squish
|
33
|
+
# SELECT * FROM table
|
34
|
+
# WHERE id = 1
|
35
|
+
# SQL
|
36
|
+
#
|
37
|
+
# execute(<<~SQL.squish, "Post Load")
|
38
|
+
# SELECT * FROM posts
|
39
|
+
# WHERE post_id = 1
|
40
|
+
# SQL
|
41
|
+
#
|
42
|
+
class SquishedSQLHeredocs < Base
|
43
|
+
include Heredoc
|
44
|
+
extend AutoCorrector
|
45
|
+
|
46
|
+
SQL = 'SQL'
|
47
|
+
SQUISH = '.squish'
|
48
|
+
MSG = 'Use `%<expect>s` instead of `%<current>s`.'
|
49
|
+
|
50
|
+
def on_heredoc(node)
|
51
|
+
return unless offense_detected?(node)
|
52
|
+
|
53
|
+
add_offense(node) do |corrector|
|
54
|
+
corrector.insert_after(node, SQUISH)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def offense_detected?(node)
|
61
|
+
sql_heredoc?(node) && !using_squish?(node)
|
62
|
+
end
|
63
|
+
|
64
|
+
def sql_heredoc?(node)
|
65
|
+
delimiter_string(node) == SQL
|
66
|
+
end
|
67
|
+
|
68
|
+
def using_squish?(node)
|
69
|
+
node.parent&.send_type? && node.parent&.method?(:squish)
|
70
|
+
end
|
71
|
+
|
72
|
+
def message(node)
|
73
|
+
format(
|
74
|
+
MSG,
|
75
|
+
expect: "#{node.source}#{SQUISH}",
|
76
|
+
current: node.source
|
77
|
+
)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|