rubocop-rails 2.19.1 → 2.20.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config/default.yml +28 -6
- data/lib/rubocop/cop/rails/assert_not.rb +0 -1
- data/lib/rubocop/cop/rails/date.rb +11 -2
- data/lib/rubocop/cop/rails/file_path.rb +126 -13
- data/lib/rubocop/cop/rails/find_each.rb +1 -1
- data/lib/rubocop/cop/rails/i18n_locale_texts.rb +5 -1
- data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +22 -2
- data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +2 -2
- data/lib/rubocop/cop/rails/not_null_column.rb +1 -1
- data/lib/rubocop/cop/rails/refute_methods.rb +0 -1
- data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +0 -1
- data/lib/rubocop/cop/rails/three_state_boolean_column.rb +2 -4
- data/lib/rubocop/cop/rails/time_zone.rb +1 -1
- data/lib/rubocop/cop/rails/transaction_exit_statement.rb +8 -1
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +14 -18
- data/lib/rubocop/rails/schema_loader/schema.rb +4 -4
- data/lib/rubocop/rails/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 227ce5b698e456412c24917c5644b2a938531440ab8c64e2b5036d6f2857a548
|
4
|
+
data.tar.gz: 41c6157da73215cca0b5d56ffa254711c2f9f4f5399c8aa3d85ac7c719958b28
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: afafd2f9293f4592cc914fdb42c6742900681574d5d0a27dc2031eddb3446b419ac04a77a149e0169ab89a0bb7afe4e0481b3ff889631345a0227b0d24a2c185
|
7
|
+
data.tar.gz: a90108eed94c1cedbe1b9a059b60cae51465cffd5a8612f56a0548182b6f992e3e626125e4a4f2f74ceda491a91cdcacb0bd8206ebf94d7d245841572639b556
|
data/config/default.yml
CHANGED
@@ -6,6 +6,7 @@ inherit_mode:
|
|
6
6
|
|
7
7
|
AllCops:
|
8
8
|
Exclude:
|
9
|
+
- app/assets/**/*
|
9
10
|
- bin/*
|
10
11
|
# Exclude db/schema.rb and db/[CONFIGURATION_NAMESPACE]_schema.rb by default.
|
11
12
|
# See: https://guides.rubyonrails.org/active_record_multiple_databases.html#setting-up-your-application
|
@@ -47,6 +48,19 @@ Lint/NumberConversion:
|
|
47
48
|
- in_milliseconds
|
48
49
|
AllowedPatterns: []
|
49
50
|
|
51
|
+
Lint/RedundantSafeNavigation:
|
52
|
+
# Add `presence` and `present?` methods to the default of the RuboCop core.
|
53
|
+
# https://github.com/rubocop/rubocop/blob/v1.51.0/config/default.yml#L2148-L2159
|
54
|
+
AllowedMethods:
|
55
|
+
- instance_of?
|
56
|
+
- kind_of?
|
57
|
+
- is_a?
|
58
|
+
- eql?
|
59
|
+
- respond_to?
|
60
|
+
- equal?
|
61
|
+
- presence
|
62
|
+
- present?
|
63
|
+
|
50
64
|
Rails:
|
51
65
|
Enabled: true
|
52
66
|
DocumentationBaseURL: https://docs.rubocop.org/rubocop-rails
|
@@ -146,8 +160,9 @@ Rails/AddColumnIndex:
|
|
146
160
|
index might be used.
|
147
161
|
Enabled: pending
|
148
162
|
VersionAdded: '2.11'
|
163
|
+
VersionChanged: '2.20'
|
149
164
|
Include:
|
150
|
-
- db
|
165
|
+
- db/**/*.rb
|
151
166
|
|
152
167
|
Rails/AfterCommitOverride:
|
153
168
|
Description: >-
|
@@ -235,12 +250,13 @@ Rails/BulkChangeTable:
|
|
235
250
|
- https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html
|
236
251
|
Enabled: true
|
237
252
|
VersionAdded: '0.57'
|
253
|
+
VersionChanged: '2.20'
|
238
254
|
Database: null
|
239
255
|
SupportedDatabases:
|
240
256
|
- mysql
|
241
257
|
- postgresql
|
242
258
|
Include:
|
243
|
-
- db
|
259
|
+
- db/**/*.rb
|
244
260
|
|
245
261
|
Rails/CompactBlank:
|
246
262
|
Description: 'Checks if collection can be blank-compacted with `compact_blank`.'
|
@@ -270,18 +286,22 @@ Rails/CreateTableWithTimestamps:
|
|
270
286
|
when creating a new table.
|
271
287
|
Enabled: true
|
272
288
|
VersionAdded: '0.52'
|
289
|
+
VersionChanged: '2.20'
|
273
290
|
Include:
|
274
|
-
- db
|
291
|
+
- db/**/*.rb
|
275
292
|
Exclude:
|
276
293
|
# Respect the `active_storage_variant_records` table of `*_create_active_storage_tables.active_storage.rb`
|
294
|
+
# and `*_create_active_storage_variant_records.active_storage.rb`
|
277
295
|
# auto-generated by `bin/rails active_storage:install` even if `created_at` is not specified.
|
278
|
-
- db
|
296
|
+
- db/**/*_create_active_storage_tables.active_storage.rb
|
297
|
+
- db/**/*_create_active_storage_variant_records.active_storage.rb
|
279
298
|
|
280
299
|
Rails/Date:
|
281
300
|
Description: >-
|
282
301
|
Checks the correct usage of date aware methods,
|
283
302
|
such as Date.today, Date.current etc.
|
284
303
|
Enabled: true
|
304
|
+
SafeAutoCorrect: false
|
285
305
|
VersionAdded: '0.30'
|
286
306
|
VersionChanged: '2.11'
|
287
307
|
# The value `strict` disallows usage of `Date.today`, `Date.current`,
|
@@ -632,8 +652,9 @@ Rails/MigrationClassName:
|
|
632
652
|
Description: 'The class name of the migration should match its file name.'
|
633
653
|
Enabled: pending
|
634
654
|
VersionAdded: '2.14'
|
655
|
+
VersionChanged: '2.20'
|
635
656
|
Include:
|
636
|
-
- db
|
657
|
+
- db/**/*.rb
|
637
658
|
|
638
659
|
Rails/NegateInclude:
|
639
660
|
Description: 'Prefer `collection.exclude?(obj)` over `!collection.include?(obj)`.'
|
@@ -647,8 +668,9 @@ Rails/NotNullColumn:
|
|
647
668
|
Description: 'Do not add a NOT NULL column without a default value.'
|
648
669
|
Enabled: true
|
649
670
|
VersionAdded: '0.43'
|
671
|
+
VersionChanged: '2.20'
|
650
672
|
Include:
|
651
|
-
- db
|
673
|
+
- db/**/*.rb
|
652
674
|
|
653
675
|
Rails/OrderById:
|
654
676
|
Description: >-
|
@@ -22,6 +22,9 @@ module RuboCop
|
|
22
22
|
# And you can set a warning for `to_time` with `AllowToTime: false`.
|
23
23
|
# `AllowToTime` is `true` by default to prevent false positive on `DateTime` object.
|
24
24
|
#
|
25
|
+
# @safety
|
26
|
+
# This cop's autocorrection is unsafe because it may change handling time.
|
27
|
+
#
|
25
28
|
# @example EnforcedStyle: flexible (default)
|
26
29
|
# # bad
|
27
30
|
# Date.today
|
@@ -51,6 +54,8 @@ module RuboCop
|
|
51
54
|
# # bad
|
52
55
|
# date.to_time
|
53
56
|
class Date < Base
|
57
|
+
extend AutoCorrector
|
58
|
+
|
54
59
|
include ConfigurableEnforcedStyle
|
55
60
|
|
56
61
|
MSG = 'Do not use `Date.%<method_called>s` without zone. Use `Time.zone.%<day>s` instead.'
|
@@ -92,7 +97,9 @@ module RuboCop
|
|
92
97
|
|
93
98
|
message = format(DEPRECATED_MSG, deprecated: method[:deprecated], relevant: method[:relevant])
|
94
99
|
|
95
|
-
add_offense(node.loc.selector, message: message)
|
100
|
+
add_offense(node.loc.selector, message: message) do |corrector|
|
101
|
+
corrector.replace(node.loc.selector, method[:relevant].to_s)
|
102
|
+
end
|
96
103
|
end
|
97
104
|
end
|
98
105
|
|
@@ -108,7 +115,9 @@ module RuboCop
|
|
108
115
|
|
109
116
|
message = format(MSG, method_called: method_name, day: day)
|
110
117
|
|
111
|
-
add_offense(node.loc.selector, message: message)
|
118
|
+
add_offense(node.loc.selector, message: message) do |corrector|
|
119
|
+
corrector.replace(node.receiver.loc.name, 'Time.zone')
|
120
|
+
end
|
112
121
|
end
|
113
122
|
|
114
123
|
def extract_method_chain(node)
|
@@ -35,6 +35,8 @@ module RuboCop
|
|
35
35
|
# Rails.root.join('app', 'models', 'goober').to_s
|
36
36
|
#
|
37
37
|
class FilePath < Base
|
38
|
+
extend AutoCorrector
|
39
|
+
|
38
40
|
include ConfigurableEnforcedStyle
|
39
41
|
include RangeHelp
|
40
42
|
|
@@ -56,13 +58,10 @@ module RuboCop
|
|
56
58
|
|
57
59
|
def on_dstr(node)
|
58
60
|
return unless rails_root_nodes?(node)
|
59
|
-
return
|
60
|
-
|
61
|
-
last_child_source = node.children.last.source
|
62
|
-
return unless last_child_source.start_with?('.') || last_child_source.include?(File::SEPARATOR)
|
63
|
-
return if last_child_source.start_with?(':')
|
61
|
+
return if dstr_separated_by_colon?(node)
|
64
62
|
|
65
|
-
|
63
|
+
check_for_slash_after_rails_root_in_dstr(node)
|
64
|
+
check_for_extension_after_rails_root_join_in_dstr(node)
|
66
65
|
end
|
67
66
|
|
68
67
|
def on_send(node)
|
@@ -73,11 +72,33 @@ module RuboCop
|
|
73
72
|
|
74
73
|
private
|
75
74
|
|
75
|
+
def check_for_slash_after_rails_root_in_dstr(node)
|
76
|
+
rails_root_index = find_rails_root_index(node)
|
77
|
+
slash_node = node.children[rails_root_index + 1]
|
78
|
+
return unless slash_node&.str_type? && slash_node.source.start_with?(File::SEPARATOR)
|
79
|
+
|
80
|
+
register_offense(node, require_to_s: false) do |corrector|
|
81
|
+
autocorrect_slash_after_rails_root_in_dstr(corrector, node, rails_root_index)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def check_for_extension_after_rails_root_join_in_dstr(node)
|
86
|
+
rails_root_index = find_rails_root_index(node)
|
87
|
+
extension_node = node.children[rails_root_index + 1]
|
88
|
+
return unless extension_node?(extension_node)
|
89
|
+
|
90
|
+
register_offense(node, require_to_s: false) do |corrector|
|
91
|
+
autocorrect_extension_after_rails_root_join_in_dstr(corrector, node, rails_root_index, extension_node)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
76
95
|
def check_for_file_join_with_rails_root(node)
|
77
96
|
return unless file_join_nodes?(node)
|
78
97
|
return unless node.arguments.any? { |e| rails_root_nodes?(e) }
|
79
98
|
|
80
|
-
register_offense(node, require_to_s: true)
|
99
|
+
register_offense(node, require_to_s: true) do |corrector|
|
100
|
+
autocorrect_file_join(corrector, node)
|
101
|
+
end
|
81
102
|
end
|
82
103
|
|
83
104
|
def check_for_rails_root_join_with_string_arguments(node)
|
@@ -87,7 +108,9 @@ module RuboCop
|
|
87
108
|
return unless node.arguments.size > 1
|
88
109
|
return unless node.arguments.all?(&:str_type?)
|
89
110
|
|
90
|
-
register_offense(node, require_to_s: false)
|
111
|
+
register_offense(node, require_to_s: false) do |corrector|
|
112
|
+
autocorrect_rails_root_join_with_string_arguments(corrector, node)
|
113
|
+
end
|
91
114
|
end
|
92
115
|
|
93
116
|
def check_for_rails_root_join_with_slash_separated_path(node)
|
@@ -96,21 +119,22 @@ module RuboCop
|
|
96
119
|
return unless rails_root_join_nodes?(node)
|
97
120
|
return unless node.arguments.any? { |arg| string_with_slash?(arg) }
|
98
121
|
|
99
|
-
register_offense(node, require_to_s: false)
|
122
|
+
register_offense(node, require_to_s: false) do |corrector|
|
123
|
+
autocorrect_rails_root_join_with_slash_separated_path(corrector, node)
|
124
|
+
end
|
100
125
|
end
|
101
126
|
|
102
127
|
def string_with_slash?(node)
|
103
|
-
node.str_type? && node.source.include?(
|
128
|
+
node.str_type? && node.source.include?(File::SEPARATOR)
|
104
129
|
end
|
105
130
|
|
106
|
-
def register_offense(node, require_to_s
|
131
|
+
def register_offense(node, require_to_s:, &block)
|
107
132
|
line_range = node.loc.column...node.loc.last_column
|
108
133
|
source_range = source_range(processed_source.buffer, node.first_line, line_range)
|
109
|
-
require_to_s = false if node.dstr_type?
|
110
134
|
|
111
135
|
message = build_message(require_to_s)
|
112
136
|
|
113
|
-
add_offense(source_range, message: message)
|
137
|
+
add_offense(source_range, message: message, &block)
|
114
138
|
end
|
115
139
|
|
116
140
|
def build_message(require_to_s)
|
@@ -119,6 +143,95 @@ module RuboCop
|
|
119
143
|
|
120
144
|
format(message_template, to_s: to_s)
|
121
145
|
end
|
146
|
+
|
147
|
+
def dstr_separated_by_colon?(node)
|
148
|
+
node.children[1..].any? do |child|
|
149
|
+
child.str_type? && child.source.start_with?(':')
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def autocorrect_slash_after_rails_root_in_dstr(corrector, node, rails_root_index)
|
154
|
+
rails_root_node = node.children[rails_root_index].children.first
|
155
|
+
argument_source = extract_rails_root_join_argument_source(node, rails_root_index)
|
156
|
+
if rails_root_node.method?(:join)
|
157
|
+
append_argument(corrector, rails_root_node, argument_source)
|
158
|
+
else
|
159
|
+
replace_with_rails_root_join(corrector, rails_root_node, argument_source)
|
160
|
+
end
|
161
|
+
node.children[rails_root_index + 1..].each { |child| corrector.remove(child) }
|
162
|
+
end
|
163
|
+
|
164
|
+
def autocorrect_extension_after_rails_root_join_in_dstr(corrector, node, rails_root_index, extension_node)
|
165
|
+
rails_root_node = node.children[rails_root_index].children.first
|
166
|
+
return unless rails_root_node.arguments.last.str_type?
|
167
|
+
|
168
|
+
corrector.insert_before(rails_root_node.arguments.last.location.end, extension_node.source)
|
169
|
+
corrector.remove(extension_node)
|
170
|
+
end
|
171
|
+
|
172
|
+
def autocorrect_file_join(corrector, node)
|
173
|
+
corrector.replace(node.receiver, 'Rails.root')
|
174
|
+
corrector.remove(
|
175
|
+
range_with_surrounding_space(
|
176
|
+
range_with_surrounding_comma(
|
177
|
+
node.arguments.first.source_range,
|
178
|
+
:right
|
179
|
+
),
|
180
|
+
side: :right
|
181
|
+
)
|
182
|
+
)
|
183
|
+
corrector.insert_after(node, '.to_s')
|
184
|
+
end
|
185
|
+
|
186
|
+
def autocorrect_rails_root_join_with_string_arguments(corrector, node)
|
187
|
+
corrector.replace(node.arguments.first, %("#{node.arguments.map(&:value).join('/')}"))
|
188
|
+
node.arguments[1..].each do |argument|
|
189
|
+
corrector.remove(
|
190
|
+
range_with_surrounding_comma(
|
191
|
+
range_with_surrounding_space(
|
192
|
+
argument.source_range,
|
193
|
+
side: :left
|
194
|
+
),
|
195
|
+
:left
|
196
|
+
)
|
197
|
+
)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def autocorrect_rails_root_join_with_slash_separated_path(corrector, node)
|
202
|
+
node.arguments.each do |argument|
|
203
|
+
next unless string_with_slash?(argument)
|
204
|
+
|
205
|
+
index = argument.source.index(File::SEPARATOR)
|
206
|
+
rest = inner_range_of(argument).adjust(begin_pos: index - 1)
|
207
|
+
corrector.remove(rest)
|
208
|
+
corrector.insert_after(argument, %(, "#{rest.source.delete_prefix(File::SEPARATOR)}"))
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def inner_range_of(node)
|
213
|
+
node.location.end.with(begin_pos: node.location.begin.end_pos).adjust(end_pos: -1)
|
214
|
+
end
|
215
|
+
|
216
|
+
def find_rails_root_index(node)
|
217
|
+
node.children.index { |child| rails_root_nodes?(child) }
|
218
|
+
end
|
219
|
+
|
220
|
+
def append_argument(corrector, node, argument_source)
|
221
|
+
corrector.insert_after(node.arguments.last, %(, "#{argument_source}"))
|
222
|
+
end
|
223
|
+
|
224
|
+
def replace_with_rails_root_join(corrector, node, argument_source)
|
225
|
+
corrector.replace(node, %<Rails.root.join("#{argument_source}")>)
|
226
|
+
end
|
227
|
+
|
228
|
+
def extract_rails_root_join_argument_source(node, rails_root_index)
|
229
|
+
node.children[rails_root_index + 1..].map(&:source).join.delete_prefix(File::SEPARATOR)
|
230
|
+
end
|
231
|
+
|
232
|
+
def extension_node?(node)
|
233
|
+
node&.str_type? && node.source.start_with?('.')
|
234
|
+
end
|
122
235
|
end
|
123
236
|
end
|
124
237
|
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
|
|
@@ -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
|
@@ -36,6 +36,10 @@ module RuboCop
|
|
36
36
|
# if: -> { trusted_origin? && action_name != "admin" }
|
37
37
|
# end
|
38
38
|
class IgnoredSkipActionFilterOption < Base
|
39
|
+
extend AutoCorrector
|
40
|
+
|
41
|
+
include RangeHelp
|
42
|
+
|
39
43
|
MSG = <<~MSG.chomp.freeze
|
40
44
|
`%<ignore>s` option will be ignored when `%<prefer>s` and `%<ignore>s` are used together.
|
41
45
|
MSG
|
@@ -60,9 +64,13 @@ module RuboCop
|
|
60
64
|
options = options_hash(options)
|
61
65
|
|
62
66
|
if if_and_only?(options)
|
63
|
-
add_offense(options[:if], message: format(MSG, prefer: :only, ignore: :if))
|
67
|
+
add_offense(options[:if], message: format(MSG, prefer: :only, ignore: :if)) do |corrector|
|
68
|
+
remove_node_with_left_space_and_comma(corrector, options[:if])
|
69
|
+
end
|
64
70
|
elsif if_and_except?(options)
|
65
|
-
add_offense(options[:except], message: format(MSG, prefer: :if, ignore: :except))
|
71
|
+
add_offense(options[:except], message: format(MSG, prefer: :if, ignore: :except)) do |corrector|
|
72
|
+
remove_node_with_left_space_and_comma(corrector, options[:except])
|
73
|
+
end
|
66
74
|
end
|
67
75
|
end
|
68
76
|
|
@@ -81,6 +89,18 @@ module RuboCop
|
|
81
89
|
def if_and_except?(options)
|
82
90
|
options.key?(:if) && options.key?(:except)
|
83
91
|
end
|
92
|
+
|
93
|
+
def remove_node_with_left_space_and_comma(corrector, node)
|
94
|
+
corrector.remove(
|
95
|
+
range_with_surrounding_comma(
|
96
|
+
range_with_surrounding_space(
|
97
|
+
node.source_range,
|
98
|
+
side: :left
|
99
|
+
),
|
100
|
+
:left
|
101
|
+
)
|
102
|
+
)
|
103
|
+
end
|
84
104
|
end
|
85
105
|
end
|
86
106
|
end
|
@@ -176,14 +176,14 @@ module RuboCop
|
|
176
176
|
when :sym
|
177
177
|
[node.value]
|
178
178
|
when :array
|
179
|
-
node.values.
|
179
|
+
node.values.filter_map do |v|
|
180
180
|
case v.type
|
181
181
|
when :str
|
182
182
|
v.str_content.to_sym
|
183
183
|
when :sym
|
184
184
|
v.value
|
185
185
|
end
|
186
|
-
end
|
186
|
+
end
|
187
187
|
else
|
188
188
|
[]
|
189
189
|
end
|
@@ -45,7 +45,7 @@ module RuboCop
|
|
45
45
|
|
46
46
|
def check_add_column(node)
|
47
47
|
add_not_null_column?(node) do |type, pairs|
|
48
|
-
return if type.value == :virtual || type.value == 'virtual'
|
48
|
+
return if type.respond_to?(:value) && (type.value == :virtual || type.value == 'virtual')
|
49
49
|
|
50
50
|
check_pairs(pairs)
|
51
51
|
end
|
@@ -35,7 +35,7 @@ module RuboCop
|
|
35
35
|
PATTERN
|
36
36
|
|
37
37
|
def_node_search :change_column_null?, <<~PATTERN
|
38
|
-
(send nil? :change_column_null
|
38
|
+
(send nil? :change_column_null %1 %2 false)
|
39
39
|
PATTERN
|
40
40
|
|
41
41
|
def on_send(node)
|
@@ -46,9 +46,7 @@ module RuboCop
|
|
46
46
|
|
47
47
|
def_node = node.each_ancestor(:def, :defs).first
|
48
48
|
table_node = table_node(node)
|
49
|
-
if def_node && (table_node.nil? || change_column_null?(def_node, table_node
|
50
|
-
return
|
51
|
-
end
|
49
|
+
return if def_node && (table_node.nil? || change_column_null?(def_node, table_node, column_node))
|
52
50
|
|
53
51
|
add_offense(node)
|
54
52
|
end
|
@@ -55,7 +55,7 @@ module RuboCop
|
|
55
55
|
|
56
56
|
ACCEPTED_METHODS = %i[in_time_zone utc getlocal xmlschema iso8601 jisx0301 rfc3339 httpdate to_i to_f].freeze
|
57
57
|
|
58
|
-
TIMEZONE_SPECIFIER = /([A-z]|[+-]\d{2}:?\d{2})\z/.freeze
|
58
|
+
TIMEZONE_SPECIFIER = /([A-Za-z]|[+-]\d{2}:?\d{2})\z/.freeze
|
59
59
|
|
60
60
|
def on_const(node)
|
61
61
|
mod, klass = *node
|
@@ -34,6 +34,11 @@ module RuboCop
|
|
34
34
|
# throw if user.active?
|
35
35
|
# end
|
36
36
|
#
|
37
|
+
# # bad, as `with_lock` implicitly opens a transaction too
|
38
|
+
# ApplicationRecord.with_lock do
|
39
|
+
# break if user.active?
|
40
|
+
# end
|
41
|
+
#
|
37
42
|
# # good
|
38
43
|
# ApplicationRecord.transaction do
|
39
44
|
# # Rollback
|
@@ -91,7 +96,9 @@ module RuboCop
|
|
91
96
|
end
|
92
97
|
|
93
98
|
def nested_block?(statement_node)
|
94
|
-
|
99
|
+
block_node = statement_node.ancestors.find(&:block_type?)
|
100
|
+
|
101
|
+
RESTRICT_ON_SEND.none? { |name| block_node.method?(name) }
|
95
102
|
end
|
96
103
|
end
|
97
104
|
end
|
@@ -31,11 +31,11 @@ module RuboCop
|
|
31
31
|
RESTRICT_ON_SEND = %i[validates].freeze
|
32
32
|
|
33
33
|
def on_send(node)
|
34
|
-
return unless uniqueness_part(node)
|
35
|
-
return if condition_part?(node)
|
36
34
|
return unless schema
|
35
|
+
return unless (uniqueness_part = uniqueness_part(node))
|
36
|
+
return if uniqueness_part.falsey_literal? || condition_part?(node, uniqueness_part)
|
37
37
|
|
38
|
-
klass, table, names = find_schema_information(node)
|
38
|
+
klass, table, names = find_schema_information(node, uniqueness_part)
|
39
39
|
return unless names
|
40
40
|
return if with_index?(klass, table, names)
|
41
41
|
|
@@ -44,12 +44,12 @@ module RuboCop
|
|
44
44
|
|
45
45
|
private
|
46
46
|
|
47
|
-
def find_schema_information(node)
|
47
|
+
def find_schema_information(node, uniqueness_part)
|
48
48
|
klass = class_node(node)
|
49
49
|
return unless klass
|
50
50
|
|
51
51
|
table = schema.table_by(name: table_name(klass))
|
52
|
-
names = column_names(node)
|
52
|
+
names = column_names(node, uniqueness_part)
|
53
53
|
|
54
54
|
[klass, table, names]
|
55
55
|
end
|
@@ -71,12 +71,12 @@ module RuboCop
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
-
def column_names(node)
|
74
|
+
def column_names(node, uniqueness_part)
|
75
75
|
arg = node.first_argument
|
76
76
|
return unless arg.str_type? || arg.sym_type?
|
77
77
|
|
78
78
|
ret = [arg.value]
|
79
|
-
names_from_scope = column_names_from_scope(
|
79
|
+
names_from_scope = column_names_from_scope(uniqueness_part)
|
80
80
|
ret.concat(names_from_scope) if names_from_scope
|
81
81
|
|
82
82
|
ret = ret.flat_map do |name|
|
@@ -90,11 +90,10 @@ module RuboCop
|
|
90
90
|
ret.include?(nil) ? nil : ret.to_set
|
91
91
|
end
|
92
92
|
|
93
|
-
def column_names_from_scope(
|
94
|
-
|
95
|
-
return unless uniq.hash_type?
|
93
|
+
def column_names_from_scope(uniqueness_part)
|
94
|
+
return unless uniqueness_part.hash_type?
|
96
95
|
|
97
|
-
scope = find_scope(
|
96
|
+
scope = find_scope(uniqueness_part)
|
98
97
|
return unless scope
|
99
98
|
|
100
99
|
scope = unfreeze_scope(scope)
|
@@ -135,14 +134,11 @@ module RuboCop
|
|
135
134
|
end
|
136
135
|
end
|
137
136
|
|
138
|
-
def condition_part?(node)
|
139
|
-
pairs = node.
|
140
|
-
return unless pairs.hash_type?
|
141
|
-
|
137
|
+
def condition_part?(node, uniqueness_node)
|
138
|
+
pairs = node.last_argument
|
139
|
+
return false unless pairs.hash_type?
|
142
140
|
return true if condition_hash_part?(pairs, keys: %i[if unless])
|
143
|
-
|
144
|
-
uniqueness_node = uniqueness_part(node)
|
145
|
-
return unless uniqueness_node&.hash_type?
|
141
|
+
return false unless uniqueness_node.hash_type?
|
146
142
|
|
147
143
|
condition_hash_part?(uniqueness_node, keys: %i[if unless conditions])
|
148
144
|
end
|
@@ -83,21 +83,21 @@ module RuboCop
|
|
83
83
|
private
|
84
84
|
|
85
85
|
def build_columns(node)
|
86
|
-
each_content(node).
|
86
|
+
each_content(node).filter_map do |child|
|
87
87
|
next unless child&.send_type?
|
88
88
|
next if child.method?(:index)
|
89
89
|
|
90
90
|
Column.new(child)
|
91
|
-
end
|
91
|
+
end
|
92
92
|
end
|
93
93
|
|
94
94
|
def build_indices(node)
|
95
|
-
each_content(node).
|
95
|
+
each_content(node).filter_map do |child|
|
96
96
|
next unless child&.send_type?
|
97
97
|
next unless child.method?(:index)
|
98
98
|
|
99
99
|
Index.new(child)
|
100
|
-
end
|
100
|
+
end
|
101
101
|
end
|
102
102
|
|
103
103
|
def each_content(node, &block)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.20.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bozhidar Batsov
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2023-
|
13
|
+
date: 2023-06-19 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -219,7 +219,7 @@ metadata:
|
|
219
219
|
homepage_uri: https://docs.rubocop.org/rubocop-rails/
|
220
220
|
changelog_uri: https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md
|
221
221
|
source_code_uri: https://github.com/rubocop/rubocop-rails/
|
222
|
-
documentation_uri: https://docs.rubocop.org/rubocop-rails/2.
|
222
|
+
documentation_uri: https://docs.rubocop.org/rubocop-rails/2.20/
|
223
223
|
bug_tracker_uri: https://github.com/rubocop/rubocop-rails/issues
|
224
224
|
rubygems_mfa_required: 'true'
|
225
225
|
post_install_message:
|
@@ -230,7 +230,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
230
230
|
requirements:
|
231
231
|
- - ">="
|
232
232
|
- !ruby/object:Gem::Version
|
233
|
-
version: 2.
|
233
|
+
version: 2.7.0
|
234
234
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
235
235
|
requirements:
|
236
236
|
- - ">="
|