rubocop-rails 2.20.2 → 2.22.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 +6 -2
- data/config/default.yml +68 -8
- data/lib/rubocop/cop/mixin/database_type_resolvable.rb +66 -0
- data/lib/rubocop/cop/mixin/index_method.rb +2 -2
- data/lib/rubocop/cop/rails/action_controller_flash_before_render.rb +1 -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/bulk_change_table.rb +5 -38
- data/lib/rubocop/cop/rails/dangerous_column_names.rb +447 -0
- data/lib/rubocop/cop/rails/date.rb +1 -1
- data/lib/rubocop/cop/rails/duplicate_association.rb +69 -12
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +3 -3
- data/lib/rubocop/cop/rails/env_local.rb +46 -0
- data/lib/rubocop/cop/rails/file_path.rb +4 -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_status.rb +4 -3
- data/lib/rubocop/cop/rails/i18n_lazy_lookup.rb +63 -13
- data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +7 -8
- data/lib/rubocop/cop/rails/not_null_column.rb +13 -3
- data/lib/rubocop/cop/rails/output.rb +3 -2
- data/lib/rubocop/cop/rails/rake_environment.rb +20 -4
- data/lib/rubocop/cop/rails/redundant_active_record_all_method.rb +207 -0
- data/lib/rubocop/cop/rails/redundant_presence_validation_on_belongs_to.rb +7 -0
- data/lib/rubocop/cop/rails/reversible_migration.rb +1 -1
- data/lib/rubocop/cop/rails/root_pathname_methods.rb +38 -4
- data/lib/rubocop/cop/rails/save_bang.rb +9 -4
- data/lib/rubocop/cop/rails/schema_comment.rb +16 -10
- data/lib/rubocop/cop/rails/select_map.rb +78 -0
- data/lib/rubocop/cop/rails/time_zone.rb +12 -5
- data/lib/rubocop/cop/rails/transaction_exit_statement.rb +29 -10
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +1 -1
- data/lib/rubocop/cop/rails/unknown_env.rb +5 -1
- data/lib/rubocop/cop/rails/unused_render_content.rb +67 -0
- data/lib/rubocop/cop/rails/where_exists.rb +0 -1
- data/lib/rubocop/cop/rails_cops.rb +6 -0
- data/lib/rubocop/rails/schema_loader.rb +1 -1
- data/lib/rubocop/rails/version.rb +1 -1
- data/lib/rubocop-rails.rb +8 -0
- metadata +9 -3
@@ -0,0 +1,447 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# Avoid dangerous column names.
|
7
|
+
#
|
8
|
+
# Some column names are considered dangerous because they would overwrite methods already defined.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# # bad
|
12
|
+
# add_column :users, :save
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# add_column :users, :saved
|
16
|
+
class DangerousColumnNames < Base # rubocop:disable Metrics/ClassLength
|
17
|
+
COLUMN_TYPE_METHOD_NAMES = %i[
|
18
|
+
bigint
|
19
|
+
binary
|
20
|
+
blob
|
21
|
+
boolean
|
22
|
+
date
|
23
|
+
datetime
|
24
|
+
decimal
|
25
|
+
float
|
26
|
+
integer
|
27
|
+
numeric
|
28
|
+
primary_key
|
29
|
+
string
|
30
|
+
text
|
31
|
+
time
|
32
|
+
].to_set.freeze
|
33
|
+
|
34
|
+
# Generated from `ActiveRecord::AttributeMethods.dangerous_attribute_methods` on activerecord 7.1.0.
|
35
|
+
# rubocop:disable Metrics/CollectionLiteralLength
|
36
|
+
DANGEROUS_COLUMN_NAMES = %w[
|
37
|
+
__callbacks
|
38
|
+
__id__
|
39
|
+
_assign_attribute
|
40
|
+
_assign_attributes
|
41
|
+
_before_commit_callbacks
|
42
|
+
_commit_callbacks
|
43
|
+
_committed_already_called
|
44
|
+
_create_callbacks
|
45
|
+
_create_record
|
46
|
+
_delete_row
|
47
|
+
_destroy
|
48
|
+
_destroy_callbacks
|
49
|
+
_ensure_no_duplicate_errors
|
50
|
+
_find_callbacks
|
51
|
+
_find_record
|
52
|
+
_has_attribute
|
53
|
+
_initialize_callbacks
|
54
|
+
_lock_value_for_database
|
55
|
+
_merge_attributes
|
56
|
+
_primary_key_constraints_hash
|
57
|
+
_raise_readonly_record_error
|
58
|
+
_raise_record_not_destroyed
|
59
|
+
_raise_record_not_touched_error
|
60
|
+
_read_attribute
|
61
|
+
_record_changed
|
62
|
+
_reflections
|
63
|
+
_rollback_callbacks
|
64
|
+
_run_before_commit_callbacks
|
65
|
+
_run_commit_callbacks
|
66
|
+
_run_create_callbacks
|
67
|
+
_run_destroy_callbacks
|
68
|
+
_run_find_callbacks
|
69
|
+
_run_initialize_callbacks
|
70
|
+
_run_rollback_callbacks
|
71
|
+
_run_save_callbacks
|
72
|
+
_run_touch_callbacks
|
73
|
+
_run_update_callbacks
|
74
|
+
_run_validate_callbacks
|
75
|
+
_run_validation_callbacks
|
76
|
+
_save_callbacks
|
77
|
+
_touch_callbacks
|
78
|
+
_touch_row
|
79
|
+
_trigger_destroy_callback
|
80
|
+
_trigger_update_callback
|
81
|
+
_update_callbacks
|
82
|
+
_update_record
|
83
|
+
_update_row
|
84
|
+
_validate_callbacks
|
85
|
+
_validation_callbacks
|
86
|
+
_validators
|
87
|
+
_write_attribute
|
88
|
+
[]
|
89
|
+
[]=
|
90
|
+
accessed_fields
|
91
|
+
add_to_transaction
|
92
|
+
aggregate_reflections
|
93
|
+
all_timestamp_attributes_in_model
|
94
|
+
allow_destroy
|
95
|
+
apply_scoping
|
96
|
+
around_save_collection_association
|
97
|
+
assign_attributes
|
98
|
+
assign_multiparameter_attributes
|
99
|
+
assign_nested_attributes_for_collection_association
|
100
|
+
assign_nested_attributes_for_one_to_one_association
|
101
|
+
assign_nested_parameter_attributes
|
102
|
+
assign_to_or_mark_for_destruction
|
103
|
+
associated_records_to_validate_or_save
|
104
|
+
association
|
105
|
+
association_cached
|
106
|
+
association_foreign_key_changed
|
107
|
+
association_instance_get
|
108
|
+
association_instance_set
|
109
|
+
association_valid
|
110
|
+
attachment_changes
|
111
|
+
attachment_reflections
|
112
|
+
attribute
|
113
|
+
attribute_aliases
|
114
|
+
attribute_before_last_save
|
115
|
+
attribute_before_type_cast
|
116
|
+
attribute_came_from_user
|
117
|
+
attribute_change
|
118
|
+
attribute_change_to_be_saved
|
119
|
+
attribute_changed
|
120
|
+
attribute_changed_in_place
|
121
|
+
attribute_for_database
|
122
|
+
attribute_for_inspect
|
123
|
+
attribute_in_database
|
124
|
+
attribute_method
|
125
|
+
attribute_method_matchers
|
126
|
+
attribute_missing
|
127
|
+
attribute_names
|
128
|
+
attribute_names_for_partial_inserts
|
129
|
+
attribute_names_for_partial_updates
|
130
|
+
attribute_names_for_serialization
|
131
|
+
attribute_present
|
132
|
+
attribute_previous_change
|
133
|
+
attribute_previously_changed
|
134
|
+
attribute_previously_was
|
135
|
+
attribute_was
|
136
|
+
attribute_will_change
|
137
|
+
attribute=
|
138
|
+
attributes
|
139
|
+
attributes_before_type_cast
|
140
|
+
attributes_for_create
|
141
|
+
attributes_for_database
|
142
|
+
attributes_for_update
|
143
|
+
attributes_in_database
|
144
|
+
attributes_with_values
|
145
|
+
attributes=
|
146
|
+
automatic_scope_inversing
|
147
|
+
becomes
|
148
|
+
before_committed
|
149
|
+
belongs_to_touch_method
|
150
|
+
broadcast_action
|
151
|
+
broadcast_action_later
|
152
|
+
broadcast_action_later_to
|
153
|
+
broadcast_action_to
|
154
|
+
broadcast_after_to
|
155
|
+
broadcast_append
|
156
|
+
broadcast_append_later
|
157
|
+
broadcast_append_later_to
|
158
|
+
broadcast_append_to
|
159
|
+
broadcast_before_to
|
160
|
+
broadcast_prepend
|
161
|
+
broadcast_prepend_later
|
162
|
+
broadcast_prepend_later_to
|
163
|
+
broadcast_prepend_to
|
164
|
+
broadcast_remove
|
165
|
+
broadcast_remove_to
|
166
|
+
broadcast_render
|
167
|
+
broadcast_render_later
|
168
|
+
broadcast_render_later_to
|
169
|
+
broadcast_render_to
|
170
|
+
broadcast_rendering_with_defaults
|
171
|
+
broadcast_replace
|
172
|
+
broadcast_replace_later
|
173
|
+
broadcast_replace_later_to
|
174
|
+
broadcast_replace_to
|
175
|
+
broadcast_target_default
|
176
|
+
broadcast_update
|
177
|
+
broadcast_update_later
|
178
|
+
broadcast_update_later_to
|
179
|
+
broadcast_update_to
|
180
|
+
build_decrypt_attribute_assignments
|
181
|
+
build_encrypt_attribute_assignments
|
182
|
+
cache_key
|
183
|
+
cache_key_with_version
|
184
|
+
cache_timestamp_format
|
185
|
+
cache_version
|
186
|
+
cache_versioning
|
187
|
+
call_reject_if
|
188
|
+
can_use_fast_cache_version
|
189
|
+
cant_modify_encrypted_attributes_when_frozen
|
190
|
+
changed
|
191
|
+
changed_attribute_names_to_save
|
192
|
+
changed_attributes
|
193
|
+
changed_for_autosave
|
194
|
+
changes
|
195
|
+
changes_applied
|
196
|
+
changes_to_save
|
197
|
+
check_record_limit
|
198
|
+
ciphertext_for
|
199
|
+
class
|
200
|
+
clear_attribute_change
|
201
|
+
clear_attribute_changes
|
202
|
+
clear_changes_information
|
203
|
+
clear_timestamp_attributes
|
204
|
+
clear_transaction_record_state
|
205
|
+
clone
|
206
|
+
collection_cache_versioning
|
207
|
+
column_for_attribute
|
208
|
+
committed
|
209
|
+
connection_handler
|
210
|
+
create_or_update
|
211
|
+
current_time_from_proper_timezone
|
212
|
+
custom_inspect_method_defined
|
213
|
+
custom_validation_context
|
214
|
+
decrement
|
215
|
+
decrypt
|
216
|
+
decrypt_attributes
|
217
|
+
decrypt_rich_texts
|
218
|
+
default_connection_handler
|
219
|
+
default_role
|
220
|
+
default_scope_override
|
221
|
+
default_scopes
|
222
|
+
default_shard
|
223
|
+
default_validation_context
|
224
|
+
defined_enums
|
225
|
+
delete
|
226
|
+
destroy
|
227
|
+
destroy_association_async_job
|
228
|
+
destroy_associations
|
229
|
+
destroy_row
|
230
|
+
destroyed
|
231
|
+
destroyed_by_association
|
232
|
+
destroyed_by_association=
|
233
|
+
dup
|
234
|
+
each_counter_cached_associations
|
235
|
+
encode_with
|
236
|
+
encrypt
|
237
|
+
encrypt_attributes
|
238
|
+
encrypt_rich_texts
|
239
|
+
encryptable_rich_texts
|
240
|
+
encrypted_attribute
|
241
|
+
encrypted_attributes
|
242
|
+
encrypted_attributes=
|
243
|
+
ensure_proper_type
|
244
|
+
errors
|
245
|
+
execute_callstack_for_multiparameter_attributes
|
246
|
+
extract_callstack_for_multiparameter_attributes
|
247
|
+
find_parameter_position
|
248
|
+
forget_attribute_assignments
|
249
|
+
format_for_inspect
|
250
|
+
freeze
|
251
|
+
from_json
|
252
|
+
frozen?
|
253
|
+
halted_callback_hook
|
254
|
+
has_attribute
|
255
|
+
has_changes_to_save
|
256
|
+
has_defer_touch_attrs
|
257
|
+
has_destroy_flag
|
258
|
+
has_encrypted_attributes
|
259
|
+
has_encrypted_rich_texts
|
260
|
+
has_transactional_callbacks
|
261
|
+
hash
|
262
|
+
id
|
263
|
+
id_before_type_cast
|
264
|
+
id_for_database
|
265
|
+
id_in_database
|
266
|
+
id_was
|
267
|
+
id=
|
268
|
+
include_root_in_json
|
269
|
+
increment
|
270
|
+
init_internals
|
271
|
+
init_with
|
272
|
+
init_with_attributes
|
273
|
+
initialize_internals_callback
|
274
|
+
inspection_filter
|
275
|
+
invalid
|
276
|
+
lock
|
277
|
+
lock_optimistically
|
278
|
+
locking_enabled
|
279
|
+
logger
|
280
|
+
mark_for_destruction
|
281
|
+
marked_for_destruction
|
282
|
+
matched_attribute_method
|
283
|
+
max_updated_column_timestamp
|
284
|
+
missing_attribute
|
285
|
+
model_name
|
286
|
+
mutations_before_last_save
|
287
|
+
mutations_from_database
|
288
|
+
nested_attributes_options
|
289
|
+
nested_records_changed_for_autosave
|
290
|
+
new_record
|
291
|
+
no_touching
|
292
|
+
normalize_reflection_attribute
|
293
|
+
object_id
|
294
|
+
partial_inserts
|
295
|
+
partial_updates
|
296
|
+
perform_validations
|
297
|
+
persisted
|
298
|
+
pk_attribute
|
299
|
+
pluralize_table_names
|
300
|
+
populate_with_current_scope_attributes
|
301
|
+
previous_changes
|
302
|
+
previously_new_record
|
303
|
+
previously_persisted
|
304
|
+
primary_key_prefix_type
|
305
|
+
query_attribute
|
306
|
+
raise_nested_attributes_record_not_found
|
307
|
+
raise_validation_error
|
308
|
+
raw_timestamp_to_cache_version
|
309
|
+
read_attribute
|
310
|
+
read_attribute_before_type_cast
|
311
|
+
read_attribute_for_serialization
|
312
|
+
read_attribute_for_validation
|
313
|
+
read_store_attribute
|
314
|
+
readonly
|
315
|
+
record_timestamps
|
316
|
+
record_timestamps=
|
317
|
+
reject_new_record
|
318
|
+
reload
|
319
|
+
remember_transaction_record_state
|
320
|
+
respond_to_without_attributes
|
321
|
+
restore_attribute
|
322
|
+
restore_attributes
|
323
|
+
restore_transaction_record_state
|
324
|
+
rolledback
|
325
|
+
run_callbacks
|
326
|
+
run_validations
|
327
|
+
sanitize_for_mass_assignment
|
328
|
+
sanitize_forbidden_attributes
|
329
|
+
save
|
330
|
+
save_belongs_to_association
|
331
|
+
save_collection_association
|
332
|
+
save_has_one_association
|
333
|
+
saved_change_to_attribute
|
334
|
+
saved_changes
|
335
|
+
serializable_add_includes
|
336
|
+
serializable_attributes
|
337
|
+
serializable_hash
|
338
|
+
should_record_timestamps
|
339
|
+
signed_id
|
340
|
+
signed_id_verifier_secret
|
341
|
+
skip_time_zone_conversion_for_attributes
|
342
|
+
slice
|
343
|
+
store_accessor_for
|
344
|
+
store_full_class_name
|
345
|
+
store_full_sti_class
|
346
|
+
strict_loaded_associations
|
347
|
+
strict_loading
|
348
|
+
strict_loading_mode
|
349
|
+
strict_loading_n_plus_one_only
|
350
|
+
surreptitiously_touch
|
351
|
+
table_name_prefix
|
352
|
+
table_name_suffix
|
353
|
+
time_zone_aware_attributes
|
354
|
+
time_zone_aware_types
|
355
|
+
timestamp_attributes_for_create_in_model
|
356
|
+
timestamp_attributes_for_update_in_model
|
357
|
+
to_ary
|
358
|
+
to_gid
|
359
|
+
to_gid_param
|
360
|
+
to_global_id
|
361
|
+
to_key
|
362
|
+
to_model
|
363
|
+
to_partial_path
|
364
|
+
to_sgid
|
365
|
+
to_sgid_param
|
366
|
+
to_signed_global_id
|
367
|
+
toggle
|
368
|
+
touch
|
369
|
+
touch_deferred_attributes
|
370
|
+
touch_later
|
371
|
+
transaction
|
372
|
+
transaction_include_any_action
|
373
|
+
trigger_transactional_callbacks
|
374
|
+
type_cast_attribute_value
|
375
|
+
type_for_attribute
|
376
|
+
update
|
377
|
+
update_attribute
|
378
|
+
update_column
|
379
|
+
update_columns
|
380
|
+
valid
|
381
|
+
validate
|
382
|
+
validate_collection_association
|
383
|
+
validate_encryption_allowed
|
384
|
+
validate_single_association
|
385
|
+
validates_absence_of
|
386
|
+
validates_acceptance_of
|
387
|
+
validates_comparison_of
|
388
|
+
validates_confirmation_of
|
389
|
+
validates_exclusion_of
|
390
|
+
validates_format_of
|
391
|
+
validates_inclusion_of
|
392
|
+
validates_length_of
|
393
|
+
validates_numericality_of
|
394
|
+
validates_presence_of
|
395
|
+
validates_size_of
|
396
|
+
validates_with
|
397
|
+
validation_context
|
398
|
+
validation_context=
|
399
|
+
values_at
|
400
|
+
verify_readonly_attribute
|
401
|
+
will_be_destroyed
|
402
|
+
will_save_change_to_attribute
|
403
|
+
with_lock
|
404
|
+
with_transaction_returning_status
|
405
|
+
write_attribute
|
406
|
+
write_store_attribute
|
407
|
+
].freeze
|
408
|
+
# rubocop:enable Metrics/CollectionLiteralLength
|
409
|
+
|
410
|
+
MSG = 'Avoid dangerous column names.'
|
411
|
+
|
412
|
+
RESTRICT_ON_SEND = [:add_column, :rename, :rename_column, *COLUMN_TYPE_METHOD_NAMES].freeze
|
413
|
+
|
414
|
+
def on_send(node)
|
415
|
+
column_name_node = column_name_node_from(node)
|
416
|
+
return false unless column_name_node
|
417
|
+
return false unless dangerous_column_name_node?(column_name_node)
|
418
|
+
|
419
|
+
add_offense(column_name_node)
|
420
|
+
end
|
421
|
+
|
422
|
+
private
|
423
|
+
|
424
|
+
def column_name_node_from(node)
|
425
|
+
case node.method_name
|
426
|
+
when :add_column, :rename
|
427
|
+
node.arguments[1]
|
428
|
+
when :rename_column
|
429
|
+
node.arguments[2]
|
430
|
+
when *COLUMN_TYPE_METHOD_NAMES
|
431
|
+
node.arguments[0]
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
def dangerous_column_name_node?(node)
|
436
|
+
return false unless node.respond_to?(:value)
|
437
|
+
|
438
|
+
dangerous_column_name?(node.value.to_s)
|
439
|
+
end
|
440
|
+
|
441
|
+
def dangerous_column_name?(column_name)
|
442
|
+
DANGEROUS_COLUMN_NAMES.include?(column_name)
|
443
|
+
end
|
444
|
+
end
|
445
|
+
end
|
446
|
+
end
|
447
|
+
end
|
@@ -20,35 +20,92 @@ module RuboCop
|
|
20
20
|
# belongs_to :bar
|
21
21
|
# has_one :foo
|
22
22
|
#
|
23
|
+
# # bad
|
24
|
+
# has_many :foo, class_name: 'Foo'
|
25
|
+
# has_many :bar, class_name: 'Foo'
|
26
|
+
# has_one :baz
|
27
|
+
#
|
28
|
+
# # good
|
29
|
+
# has_many :bar, class_name: 'Foo'
|
30
|
+
# has_one :foo
|
31
|
+
#
|
23
32
|
class DuplicateAssociation < Base
|
24
33
|
include RangeHelp
|
25
34
|
extend AutoCorrector
|
26
35
|
include ClassSendNodeHelper
|
36
|
+
include ActiveRecordHelper
|
27
37
|
|
28
38
|
MSG = "Association `%<name>s` is defined multiple times. Don't repeat associations."
|
39
|
+
MSG_CLASS_NAME = "Association `class_name: %<name>s` is defined multiple times. Don't repeat associations."
|
29
40
|
|
30
41
|
def_node_matcher :association, <<~PATTERN
|
31
|
-
(send nil? {:belongs_to :has_one :has_many :has_and_belongs_to_many} ({sym str} $_)
|
42
|
+
(send nil? {:belongs_to :has_one :has_many :has_and_belongs_to_many} ({sym str} $_) $...)
|
43
|
+
PATTERN
|
44
|
+
|
45
|
+
def_node_matcher :class_name, <<~PATTERN
|
46
|
+
(hash (pair (sym :class_name) $_))
|
32
47
|
PATTERN
|
33
48
|
|
34
49
|
def on_class(class_node)
|
35
|
-
|
36
|
-
nodes.each do |node|
|
37
|
-
add_offense(node, message: format(MSG, name: name)) do |corrector|
|
38
|
-
next if same_line?(nodes.last, node)
|
50
|
+
return unless active_record?(class_node.parent_class)
|
39
51
|
|
40
|
-
|
41
|
-
|
42
|
-
|
52
|
+
association_nodes = association_nodes(class_node)
|
53
|
+
|
54
|
+
duplicated_association_name_nodes(association_nodes).each do |name, nodes|
|
55
|
+
register_offense(name, nodes, MSG)
|
56
|
+
end
|
57
|
+
|
58
|
+
duplicated_class_name_nodes(association_nodes).each do |class_name, nodes|
|
59
|
+
register_offense(class_name, nodes, MSG_CLASS_NAME)
|
43
60
|
end
|
44
61
|
end
|
45
62
|
|
46
63
|
private
|
47
64
|
|
48
|
-
def
|
49
|
-
|
50
|
-
|
51
|
-
|
65
|
+
def register_offense(name, nodes, message_template)
|
66
|
+
nodes.each do |node|
|
67
|
+
add_offense(node, message: format(message_template, name: name)) do |corrector|
|
68
|
+
next if same_line?(nodes.last, node)
|
69
|
+
|
70
|
+
corrector.remove(range_by_whole_lines(node.source_range, include_final_newline: true))
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def association_nodes(class_node)
|
76
|
+
class_send_nodes(class_node).select do |node|
|
77
|
+
association(node)&.first
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def duplicated_association_name_nodes(association_nodes)
|
82
|
+
grouped_associations = association_nodes.group_by do |node|
|
83
|
+
association(node).first.to_sym
|
84
|
+
end
|
85
|
+
|
86
|
+
leave_duplicated_association(grouped_associations)
|
87
|
+
end
|
88
|
+
|
89
|
+
def duplicated_class_name_nodes(association_nodes)
|
90
|
+
filtered_nodes = association_nodes.reject { |node| node.method?(:belongs_to) }
|
91
|
+
grouped_associations = filtered_nodes.group_by do |node|
|
92
|
+
arguments = association(node).last
|
93
|
+
next unless arguments.count == 1
|
94
|
+
|
95
|
+
if (class_name = class_name(arguments.first))
|
96
|
+
class_name.source
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
grouped_associations.delete(nil)
|
101
|
+
|
102
|
+
leave_duplicated_association(grouped_associations)
|
103
|
+
end
|
104
|
+
|
105
|
+
def leave_duplicated_association(grouped_associations)
|
106
|
+
grouped_associations.select do |_, nodes|
|
107
|
+
nodes.length > 1
|
108
|
+
end
|
52
109
|
end
|
53
110
|
end
|
54
111
|
end
|
@@ -74,13 +74,13 @@ module RuboCop
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def allowed_method?(node)
|
77
|
-
return unless cop_config['AllowedMethods']
|
77
|
+
return false unless cop_config['AllowedMethods']
|
78
78
|
|
79
79
|
cop_config['AllowedMethods'].include?(node.method_name.to_s)
|
80
80
|
end
|
81
81
|
|
82
82
|
def allowed_receiver?(node)
|
83
|
-
return unless cop_config['AllowedReceivers'] && node.receiver
|
83
|
+
return false unless cop_config['AllowedReceivers'] && node.receiver
|
84
84
|
|
85
85
|
cop_config['AllowedReceivers'].include?(node.receiver.source)
|
86
86
|
end
|
@@ -88,7 +88,7 @@ module RuboCop
|
|
88
88
|
# config option `WhiteList` will be deprecated soon
|
89
89
|
def whitelisted?(node)
|
90
90
|
whitelist_config = cop_config['Whitelist']
|
91
|
-
return unless whitelist_config
|
91
|
+
return false unless whitelist_config
|
92
92
|
|
93
93
|
whitelist_config.include?(node.method_name.to_s)
|
94
94
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# Checks for usage of `Rails.env.development? || Rails.env.test?` which
|
7
|
+
# can be replaced with `Rails.env.local?`, introduced in Rails 7.1.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
#
|
11
|
+
# # bad
|
12
|
+
# Rails.env.development? || Rails.env.test?
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# Rails.env.local?
|
16
|
+
#
|
17
|
+
class EnvLocal < Base
|
18
|
+
extend AutoCorrector
|
19
|
+
extend TargetRailsVersion
|
20
|
+
|
21
|
+
MSG = 'Use `Rails.env.local?` instead.'
|
22
|
+
LOCAL_ENVIRONMENTS = %i[development? test?].to_set.freeze
|
23
|
+
|
24
|
+
minimum_target_rails_version 7.1
|
25
|
+
|
26
|
+
# @!method rails_env_local_candidate?(node)
|
27
|
+
def_node_matcher :rails_env_local_candidate?, <<~PATTERN
|
28
|
+
(or
|
29
|
+
(send (send (const {cbase nil? } :Rails) :env) $%LOCAL_ENVIRONMENTS)
|
30
|
+
(send (send (const {cbase nil? } :Rails) :env) $%LOCAL_ENVIRONMENTS)
|
31
|
+
)
|
32
|
+
PATTERN
|
33
|
+
|
34
|
+
def on_or(node)
|
35
|
+
rails_env_local_candidate?(node) do |*environments|
|
36
|
+
next unless environments.to_set == LOCAL_ENVIRONMENTS
|
37
|
+
|
38
|
+
add_offense(node) do |corrector|
|
39
|
+
corrector.replace(node, 'Rails.env.local?')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -180,6 +180,9 @@ module RuboCop
|
|
180
180
|
side: :right
|
181
181
|
)
|
182
182
|
)
|
183
|
+
node.arguments.filter(&:str_type?).each do |argument|
|
184
|
+
corrector.replace(argument, argument.value.delete_prefix('/').inspect)
|
185
|
+
end
|
183
186
|
corrector.insert_after(node, '.to_s')
|
184
187
|
end
|
185
188
|
|
@@ -230,7 +233,7 @@ module RuboCop
|
|
230
233
|
end
|
231
234
|
|
232
235
|
def extension_node?(node)
|
233
|
-
node&.str_type? && node.source.
|
236
|
+
node&.str_type? && node.source.match?(/\A\.[A-Za-z]+/)
|
234
237
|
end
|
235
238
|
end
|
236
239
|
end
|
@@ -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
|