rubocop-rails 2.17.3 → 2.18.0
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/config/default.yml +52 -26
- data/lib/rubocop/cop/rails/action_controller_flash_before_render.rb +14 -6
- data/lib/rubocop/cop/rails/action_controller_test_case.rb +1 -1
- data/lib/rubocop/cop/rails/active_record_aliases.rb +2 -0
- data/lib/rubocop/cop/rails/belongs_to.rb +0 -3
- data/lib/rubocop/cop/rails/blank.rb +1 -1
- data/lib/rubocop/cop/rails/bulk_change_table.rb +1 -4
- data/lib/rubocop/cop/rails/deprecated_active_model_errors_methods.rb +1 -1
- data/lib/rubocop/cop/rails/freeze_time.rb +3 -0
- data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +2 -2
- data/lib/rubocop/cop/rails/i18n_locale_texts.rb +2 -2
- data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +0 -2
- data/lib/rubocop/cop/rails/inverse_of.rb +0 -3
- data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +17 -7
- data/lib/rubocop/cop/rails/negate_include.rb +1 -1
- data/lib/rubocop/cop/rails/not_null_column.rb +9 -6
- data/lib/rubocop/cop/rails/pluck.rb +12 -0
- data/lib/rubocop/cop/rails/presence.rb +2 -2
- data/lib/rubocop/cop/rails/present.rb +1 -1
- data/lib/rubocop/cop/rails/response_parsed_body.rb +57 -0
- data/lib/rubocop/cop/rails/reversible_migration.rb +4 -29
- data/lib/rubocop/cop/rails/root_pathname_methods.rb +20 -7
- data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +8 -1
- data/lib/rubocop/cop/rails/time_zone.rb +15 -2
- data/lib/rubocop/cop/rails/transaction_exit_statement.rb +0 -2
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +10 -1
- data/lib/rubocop/cop/rails/unused_ignored_columns.rb +6 -1
- data/lib/rubocop/cop/rails/where_missing.rb +9 -2
- data/lib/rubocop/cop/rails_cops.rb +1 -0
- data/lib/rubocop/rails/version.rb +1 -1
- data/lib/rubocop/rails.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f1cbc229165ee81ea84fc26d1c6482f917d8e8177827b139cf36974acff0176
|
4
|
+
data.tar.gz: 23cefe2f0434e5ef4c86856221f1336bfc55ffbacfd09f2dc9a24552b633d355
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59f9af07f060ff82a64bbf9db4af4d8ebb56dfada8310073bca25fde87736ef8fa0891e6f3ba997e8b847eef6218d93f25739b8022a8cb68e9aae970e8b2c674
|
7
|
+
data.tar.gz: a4415117082d7ccaeb8349f1ee31c9dba95bb6ea54bed77b176bcdd59b03cf4e2702f99c05414ff1e9028c48f96dce2f729eb2a2b98f91183cba3cb143e08894
|
data/LICENSE.txt
CHANGED
data/config/default.yml
CHANGED
@@ -46,23 +46,6 @@ Lint/NumberConversion:
|
|
46
46
|
- fortnights
|
47
47
|
- in_milliseconds
|
48
48
|
AllowedPatterns: []
|
49
|
-
# Deprecated.
|
50
|
-
IgnoredMethods:
|
51
|
-
- ago
|
52
|
-
- from_now
|
53
|
-
- second
|
54
|
-
- seconds
|
55
|
-
- minute
|
56
|
-
- minutes
|
57
|
-
- hour
|
58
|
-
- hours
|
59
|
-
- day
|
60
|
-
- days
|
61
|
-
- week
|
62
|
-
- weeks
|
63
|
-
- fortnight
|
64
|
-
- fortnights
|
65
|
-
- in_milliseconds
|
66
49
|
|
67
50
|
Rails:
|
68
51
|
Enabled: true
|
@@ -135,7 +118,9 @@ Rails/ActiveRecordOverride:
|
|
135
118
|
Check for overriding Active Record methods instead of using
|
136
119
|
callbacks.
|
137
120
|
Enabled: true
|
121
|
+
Severity: warning
|
138
122
|
VersionAdded: '0.67'
|
123
|
+
VersionChanged: '2.18'
|
139
124
|
Include:
|
140
125
|
- app/models/**/*.rb
|
141
126
|
|
@@ -226,6 +211,9 @@ Rails/BelongsTo:
|
|
226
211
|
Description: >-
|
227
212
|
Use `optional: true` instead of `required: false` for
|
228
213
|
`belongs_to` relations.
|
214
|
+
Reference:
|
215
|
+
- https://guides.rubyonrails.org/5_0_release_notes.html
|
216
|
+
- https://github.com/rails/rails/pull/18937
|
229
217
|
Enabled: true
|
230
218
|
VersionAdded: '0.62'
|
231
219
|
|
@@ -244,6 +232,9 @@ Rails/Blank:
|
|
244
232
|
|
245
233
|
Rails/BulkChangeTable:
|
246
234
|
Description: 'Check whether alter queries are combinable.'
|
235
|
+
Reference:
|
236
|
+
- https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-change_table
|
237
|
+
- https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html
|
247
238
|
Enabled: true
|
248
239
|
VersionAdded: '0.57'
|
249
240
|
Database: null
|
@@ -330,9 +321,10 @@ Rails/DelegateAllowBlank:
|
|
330
321
|
Rails/DeprecatedActiveModelErrorsMethods:
|
331
322
|
Description: 'Avoid manipulating ActiveModel errors hash directly.'
|
332
323
|
Enabled: pending
|
324
|
+
Severity: warning
|
333
325
|
Safe: false
|
334
326
|
VersionAdded: '2.14'
|
335
|
-
VersionChanged: '2.
|
327
|
+
VersionChanged: '2.18'
|
336
328
|
|
337
329
|
Rails/DotSeparatedKeys:
|
338
330
|
Description: 'Enforces the use of dot-separated keys instead of `:scope` options in `I18n` translation methods.'
|
@@ -343,12 +335,16 @@ Rails/DotSeparatedKeys:
|
|
343
335
|
Rails/DuplicateAssociation:
|
344
336
|
Description: "Don't repeat associations in a model."
|
345
337
|
Enabled: pending
|
338
|
+
Severity: warning
|
346
339
|
VersionAdded: '2.14'
|
340
|
+
VersionChanged: '2.18'
|
347
341
|
|
348
342
|
Rails/DuplicateScope:
|
349
343
|
Description: 'Multiple scopes share this same where clause.'
|
350
344
|
Enabled: pending
|
345
|
+
Severity: warning
|
351
346
|
VersionAdded: '2.14'
|
347
|
+
VersionChanged: '2.18'
|
352
348
|
|
353
349
|
Rails/DurationArithmetic:
|
354
350
|
Description: 'Do not use duration as arithmetic operand with `Time.current`.'
|
@@ -463,7 +459,7 @@ Rails/FindById:
|
|
463
459
|
VersionAdded: '2.7'
|
464
460
|
|
465
461
|
Rails/FindEach:
|
466
|
-
Description: 'Prefer all.find_each over all.
|
462
|
+
Description: 'Prefer all.find_each over all.each.'
|
467
463
|
StyleGuide: 'https://rails.rubystyle.guide#find-each'
|
468
464
|
Enabled: true
|
469
465
|
VersionAdded: '0.30'
|
@@ -477,13 +473,6 @@ Rails/FindEach:
|
|
477
473
|
- select
|
478
474
|
- lock
|
479
475
|
AllowedPatterns: []
|
480
|
-
# Deprecated.
|
481
|
-
IgnoredMethods:
|
482
|
-
# Methods that don't work well with `find_each`.
|
483
|
-
- order
|
484
|
-
- limit
|
485
|
-
- select
|
486
|
-
- lock
|
487
476
|
|
488
477
|
Rails/FreezeTime:
|
489
478
|
Description: 'Prefer `freeze_time` over `travel_to` with an argument of the current time.'
|
@@ -592,6 +581,9 @@ Rails/Inquiry:
|
|
592
581
|
|
593
582
|
Rails/InverseOf:
|
594
583
|
Description: 'Checks for associations where the inverse cannot be determined automatically.'
|
584
|
+
Reference:
|
585
|
+
- https://guides.rubyonrails.org/association_basics.html#bi-directional-associations
|
586
|
+
- https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Setting+Inverses
|
595
587
|
Enabled: true
|
596
588
|
VersionAdded: '0.52'
|
597
589
|
IgnoreScopes: false
|
@@ -695,7 +687,9 @@ Rails/Pluck:
|
|
695
687
|
Description: 'Prefer `pluck` over `map { ... }`.'
|
696
688
|
StyleGuide: 'https://rails.rubystyle.guide#pluck'
|
697
689
|
Enabled: 'pending'
|
690
|
+
Safe: false
|
698
691
|
VersionAdded: '2.7'
|
692
|
+
VersionChanged: '2.18'
|
699
693
|
|
700
694
|
Rails/PluckId:
|
701
695
|
Description: 'Use `ids` instead of `pluck(:id)` or `pluck(primary_key)`.'
|
@@ -847,6 +841,17 @@ Rails/RequireDependency:
|
|
847
841
|
Enabled: false
|
848
842
|
VersionAdded: '2.10'
|
849
843
|
|
844
|
+
Rails/ResponseParsedBody:
|
845
|
+
Description: Prefer `response.parsed_body` to `JSON.parse(response.body)`.
|
846
|
+
Enabled: pending
|
847
|
+
SafeAutoCorrect: false
|
848
|
+
VersionAdded: '2.18'
|
849
|
+
Include:
|
850
|
+
- spec/controllers/**/*.rb
|
851
|
+
- spec/requests/**/*.rb
|
852
|
+
- test/controllers/**/*.rb
|
853
|
+
- test/integration/**/*.rb
|
854
|
+
|
850
855
|
Rails/ReversibleMigration:
|
851
856
|
Description: 'Checks whether the change method of the migration file is reversible.'
|
852
857
|
StyleGuide: 'https://rails.rubystyle.guide#reversible-migration'
|
@@ -1038,10 +1043,14 @@ Rails/TopLevelHashWithIndifferentAccess:
|
|
1038
1043
|
Description: 'Identifies top-level `HashWithIndifferentAccess`.'
|
1039
1044
|
Reference: 'https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#top-level-hashwithindifferentaccess-is-soft-deprecated'
|
1040
1045
|
Enabled: pending
|
1046
|
+
Severity: warning
|
1041
1047
|
VersionAdded: '2.16'
|
1048
|
+
VersionChanged: '2.18'
|
1042
1049
|
|
1043
1050
|
Rails/TransactionExitStatement:
|
1044
1051
|
Description: 'Avoid the usage of `return`, `break` and `throw` in transaction blocks.'
|
1052
|
+
Reference:
|
1053
|
+
- https://github.com/rails/rails/commit/15aa4200e083
|
1045
1054
|
Enabled: pending
|
1046
1055
|
VersionAdded: '2.14'
|
1047
1056
|
|
@@ -1066,7 +1075,9 @@ Rails/UniqueValidationWithoutIndex:
|
|
1066
1075
|
Rails/UnknownEnv:
|
1067
1076
|
Description: 'Use correct environment name.'
|
1068
1077
|
Enabled: true
|
1078
|
+
Severity: warning
|
1069
1079
|
VersionAdded: '0.51'
|
1080
|
+
VersionChanged: '2.18'
|
1070
1081
|
Environments:
|
1071
1082
|
- development
|
1072
1083
|
- test
|
@@ -1121,12 +1132,27 @@ Rails/WhereNot:
|
|
1121
1132
|
Rails/WhereNotWithMultipleConditions:
|
1122
1133
|
Description: 'Do not use `where.not(...)` with multiple conditions.'
|
1123
1134
|
Enabled: 'pending'
|
1135
|
+
Severity: warning
|
1124
1136
|
VersionAdded: '2.17'
|
1137
|
+
VersionChanged: '2.18'
|
1125
1138
|
|
1126
1139
|
# Accept `redirect_to(...) and return` and similar cases.
|
1127
1140
|
Style/AndOr:
|
1128
1141
|
EnforcedStyle: conditionals
|
1129
1142
|
|
1143
|
+
Style/FormatStringToken:
|
1144
|
+
AllowedMethods:
|
1145
|
+
- redirect
|
1146
|
+
|
1147
|
+
Style/InverseMethods:
|
1148
|
+
# `InverseMethods` are methods that can be inverted by a not (`not` or `!`)
|
1149
|
+
# The relationship of inverse methods only needs to be defined in one direction.
|
1150
|
+
# Keys and values both need to be defined as symbols.
|
1151
|
+
InverseMethods:
|
1152
|
+
:present?: :blank?
|
1153
|
+
:include?: :exclude?
|
1154
|
+
:valid?: :invalid?
|
1155
|
+
|
1130
1156
|
Style/SymbolProc:
|
1131
1157
|
AllowedMethods:
|
1132
1158
|
- define_method
|
@@ -67,17 +67,19 @@ module RuboCop
|
|
67
67
|
private
|
68
68
|
|
69
69
|
def followed_by_render?(flash_node)
|
70
|
-
|
71
|
-
context =
|
72
|
-
if (
|
73
|
-
|
70
|
+
flash_assignment_node = find_ancestor(flash_node, type: :send)
|
71
|
+
context = flash_assignment_node
|
72
|
+
if (node = context.each_ancestor(:if, :rescue).first)
|
73
|
+
return false if use_redirect_to?(context)
|
74
|
+
|
75
|
+
context = node
|
74
76
|
elsif context.right_siblings.empty?
|
75
77
|
return true
|
76
78
|
end
|
77
79
|
context = context.right_siblings
|
78
80
|
|
79
|
-
context.compact.any? do |
|
80
|
-
render?(
|
81
|
+
context.compact.any? do |render_candidate|
|
82
|
+
render?(render_candidate)
|
81
83
|
end
|
82
84
|
end
|
83
85
|
|
@@ -95,6 +97,12 @@ module RuboCop
|
|
95
97
|
def_node || block_node
|
96
98
|
end
|
97
99
|
|
100
|
+
def use_redirect_to?(context)
|
101
|
+
context.right_siblings.compact.any? do |sibling|
|
102
|
+
sibling.send_type? && sibling.method?(:redirect_to)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
98
106
|
def find_ancestor(node, type:)
|
99
107
|
node.each_ancestor(type).first
|
100
108
|
end
|
@@ -47,9 +47,6 @@ module RuboCop
|
|
47
47
|
# class Post < ApplicationRecord
|
48
48
|
# belongs_to :blog, optional: false
|
49
49
|
# end
|
50
|
-
#
|
51
|
-
# @see https://guides.rubyonrails.org/5_0_release_notes.html
|
52
|
-
# @see https://github.com/rails/rails/pull/18937
|
53
50
|
class BelongsTo < Base
|
54
51
|
extend AutoCorrector
|
55
52
|
extend TargetRailsVersion
|
@@ -8,7 +8,7 @@ module RuboCop
|
|
8
8
|
#
|
9
9
|
# Interaction with `Style/UnlessElse`:
|
10
10
|
# The configuration of `NotPresent` will not produce an offense in the
|
11
|
-
# context of `unless else` if `Style/UnlessElse` is
|
11
|
+
# context of `unless else` if `Style/UnlessElse` is enabled. This is
|
12
12
|
# to prevent interference between the autocorrection of the two cops.
|
13
13
|
#
|
14
14
|
# @safety
|
@@ -62,9 +62,6 @@ module RuboCop
|
|
62
62
|
# t.string :nickname
|
63
63
|
# end
|
64
64
|
# end
|
65
|
-
#
|
66
|
-
# @see https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-change_table
|
67
|
-
# @see https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html
|
68
65
|
class BulkChangeTable < Base
|
69
66
|
MSG_FOR_CHANGE_TABLE = <<~MSG.chomp
|
70
67
|
You can combine alter queries using `bulk: true` options.
|
@@ -216,7 +213,7 @@ module RuboCop
|
|
216
213
|
true
|
217
214
|
when POSTGRESQL
|
218
215
|
# Add bulk alter support for PostgreSQL in 5.2.0
|
219
|
-
#
|
216
|
+
# See: https://github.com/rails/rails/pull/31331
|
220
217
|
target_rails_version >= 5.2
|
221
218
|
else
|
222
219
|
false
|
@@ -41,11 +41,11 @@ module RuboCop
|
|
41
41
|
PATTERN
|
42
42
|
|
43
43
|
def_node_matcher :association_without_options?, <<~PATTERN
|
44
|
-
(send
|
44
|
+
(send _ {:has_many :has_one} _)
|
45
45
|
PATTERN
|
46
46
|
|
47
47
|
def_node_matcher :association_with_options?, <<~PATTERN
|
48
|
-
(send
|
48
|
+
(send _ {:has_many :has_one} ... (hash $...))
|
49
49
|
PATTERN
|
50
50
|
|
51
51
|
def_node_matcher :dependent_option?, <<~PATTERN
|
@@ -69,7 +69,7 @@ module RuboCop
|
|
69
69
|
class I18nLocaleTexts < Base
|
70
70
|
MSG = 'Move locale texts to the locale files in the `config/locales` directory.'
|
71
71
|
|
72
|
-
RESTRICT_ON_SEND = %i[validates redirect_to []= mail].freeze
|
72
|
+
RESTRICT_ON_SEND = %i[validates redirect_to redirect_back []= mail].freeze
|
73
73
|
|
74
74
|
def_node_search :validation_message, <<~PATTERN
|
75
75
|
(pair (sym :message) $str)
|
@@ -94,7 +94,7 @@ module RuboCop
|
|
94
94
|
add_offense(text_node)
|
95
95
|
end
|
96
96
|
return
|
97
|
-
when :redirect_to
|
97
|
+
when :redirect_to, :redirect_back
|
98
98
|
text_node = redirect_to_flash(node).to_a.last
|
99
99
|
when :[]=
|
100
100
|
text_node = flash_assignment?(node)
|
@@ -35,8 +35,6 @@ module RuboCop
|
|
35
35
|
# skip_before_action :login_required,
|
36
36
|
# if: -> { trusted_origin? && action_name != "admin" }
|
37
37
|
# end
|
38
|
-
#
|
39
|
-
# @see https://api.rubyonrails.org/classes/AbstractController/Callbacks/ClassMethods.html#method-i-_normalize_callback_options
|
40
38
|
class IgnoredSkipActionFilterOption < Base
|
41
39
|
MSG = <<~MSG.chomp.freeze
|
42
40
|
`%<ignore>s` option will be ignored when `%<prefer>s` and `%<ignore>s` are used together.
|
@@ -137,9 +137,6 @@ module RuboCop
|
|
137
137
|
# class Blog < ApplicationRecord
|
138
138
|
# has_many :posts, -> { order(published_at: :desc) }
|
139
139
|
# end
|
140
|
-
#
|
141
|
-
# @see https://guides.rubyonrails.org/association_basics.html#bi-directional-associations
|
142
|
-
# @see https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Setting+Inverses
|
143
140
|
class InverseOf < Base
|
144
141
|
SPECIFY_MSG = 'Specify an `:inverse_of` option.'
|
145
142
|
NIL_MSG = 'You specified `inverse_of: nil`, you probably meant to use `inverse_of: false`.'
|
@@ -144,19 +144,29 @@ module RuboCop
|
|
144
144
|
end
|
145
145
|
|
146
146
|
def aliased_action_methods(node, defined_methods)
|
147
|
-
alias_methods = node
|
148
|
-
|
149
|
-
hash_of_alias_methods = alias_methods.each_with_object({}) do |alias_method, result|
|
150
|
-
result[alias_method.last_argument.value] = alias_method.first_argument.value
|
151
|
-
end
|
152
|
-
|
147
|
+
alias_methods = alias_methods(node)
|
153
148
|
defined_methods.each_with_object([]) do |defined_method, aliased_method|
|
154
|
-
if (new_method_name =
|
149
|
+
if (new_method_name = alias_methods[defined_method])
|
155
150
|
aliased_method << new_method_name
|
156
151
|
end
|
157
152
|
end
|
158
153
|
end
|
159
154
|
|
155
|
+
def alias_methods(node)
|
156
|
+
result = {}
|
157
|
+
node.each_child_node(:send, :alias) do |child_node|
|
158
|
+
case child_node.type
|
159
|
+
when :send
|
160
|
+
if child_node.method?(:alias_method)
|
161
|
+
result[child_node.last_argument.value] = child_node.first_argument.value
|
162
|
+
end
|
163
|
+
when :alias
|
164
|
+
result[child_node.old_identifier.value] = child_node.new_identifier.value
|
165
|
+
end
|
166
|
+
end
|
167
|
+
result
|
168
|
+
end
|
169
|
+
|
160
170
|
# @param node [RuboCop::AST::Node]
|
161
171
|
# @return [Array<Symbol>]
|
162
172
|
def array_values(node) # rubocop:disable Metrics/MethodLength
|
@@ -21,7 +21,7 @@ module RuboCop
|
|
21
21
|
RESTRICT_ON_SEND = %i[add_column add_reference].freeze
|
22
22
|
|
23
23
|
def_node_matcher :add_not_null_column?, <<~PATTERN
|
24
|
-
(send nil? :add_column _ _ _ (hash $...))
|
24
|
+
(send nil? :add_column _ _ $_ (hash $...))
|
25
25
|
PATTERN
|
26
26
|
|
27
27
|
def_node_matcher :add_not_null_reference?, <<~PATTERN
|
@@ -44,17 +44,20 @@ module RuboCop
|
|
44
44
|
private
|
45
45
|
|
46
46
|
def check_add_column(node)
|
47
|
-
|
48
|
-
|
47
|
+
add_not_null_column?(node) do |type, pairs|
|
48
|
+
return if type.value == :virtual || type.value == 'virtual'
|
49
|
+
|
50
|
+
check_pairs(pairs)
|
51
|
+
end
|
49
52
|
end
|
50
53
|
|
51
54
|
def check_add_reference(node)
|
52
|
-
|
53
|
-
|
55
|
+
add_not_null_reference?(node) do |pairs|
|
56
|
+
check_pairs(pairs)
|
57
|
+
end
|
54
58
|
end
|
55
59
|
|
56
60
|
def check_pairs(pairs)
|
57
|
-
return unless pairs
|
58
61
|
return if pairs.any? { |pair| default_option?(pair) }
|
59
62
|
|
60
63
|
null_false = pairs.find { |pair| null_false?(pair) }
|
@@ -9,6 +9,18 @@ module RuboCop
|
|
9
9
|
# element in an enumerable. When called on an Active Record relation, it
|
10
10
|
# results in a more efficient query that only selects the necessary key.
|
11
11
|
#
|
12
|
+
# @safety
|
13
|
+
# This cop is unsafe because model can use column aliases.
|
14
|
+
#
|
15
|
+
# [source,ruby]
|
16
|
+
# ----
|
17
|
+
# # Original code
|
18
|
+
# User.select('name AS nickname').map { |user| user[:nickname] } # => array of nicknames
|
19
|
+
#
|
20
|
+
# # After autocorrection
|
21
|
+
# User.select('name AS nickname').pluck(:nickname) # => raises ActiveRecord::StatementInvalid
|
22
|
+
# ----
|
23
|
+
#
|
12
24
|
# @example
|
13
25
|
# # bad
|
14
26
|
# Post.published.map { |post| post[:title] }
|
@@ -112,10 +112,10 @@ module RuboCop
|
|
112
112
|
end
|
113
113
|
|
114
114
|
def current(node)
|
115
|
-
if node.source.include?("\n")
|
115
|
+
if !node.ternary? && node.source.include?("\n")
|
116
116
|
"#{node.loc.keyword.with(end_pos: node.condition.loc.selector.end_pos).source} ... end"
|
117
117
|
else
|
118
|
-
node.source
|
118
|
+
node.source.gsub(/\n\s*/, ' ')
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
@@ -8,7 +8,7 @@ module RuboCop
|
|
8
8
|
#
|
9
9
|
# Interaction with `Style/UnlessElse`:
|
10
10
|
# The configuration of `NotBlank` will not produce an offense in the
|
11
|
-
# context of `unless else` if `Style/UnlessElse` is
|
11
|
+
# context of `unless else` if `Style/UnlessElse` is enabled. This is
|
12
12
|
# to prevent interference between the autocorrection of the two cops.
|
13
13
|
#
|
14
14
|
# @example NotNilAndNotEmpty: true (default)
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# Prefer `response.parsed_body` to `JSON.parse(response.body)`.
|
7
|
+
#
|
8
|
+
# @safety
|
9
|
+
# This cop's autocorrection is unsafe because Content-Type may not be `application/json`. For example, the
|
10
|
+
# proprietary Content-Type provided by corporate entities such as `application/vnd.github+json` is not
|
11
|
+
# supported at `response.parsed_body` by default, so you still have to use `JSON.parse(response.body)` there.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# # bad
|
15
|
+
# JSON.parse(response.body)
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# response.parsed_body
|
19
|
+
class ResponseParsedBody < Base
|
20
|
+
extend AutoCorrector
|
21
|
+
extend TargetRailsVersion
|
22
|
+
|
23
|
+
MSG = 'Prefer `response.parsed_body` to `JSON.parse(response.body)`.'
|
24
|
+
|
25
|
+
RESTRICT_ON_SEND = %i[parse].freeze
|
26
|
+
|
27
|
+
minimum_target_rails_version 5.0
|
28
|
+
|
29
|
+
# @!method json_parse_response_body?(node)
|
30
|
+
def_node_matcher :json_parse_response_body?, <<~PATTERN
|
31
|
+
(send
|
32
|
+
(const {nil? cbase} :JSON)
|
33
|
+
:parse
|
34
|
+
(send
|
35
|
+
(send nil? :response)
|
36
|
+
:body
|
37
|
+
)
|
38
|
+
)
|
39
|
+
PATTERN
|
40
|
+
|
41
|
+
def on_send(node)
|
42
|
+
return unless json_parse_response_body?(node)
|
43
|
+
|
44
|
+
add_offense(node) do |corrector|
|
45
|
+
autocorrect(corrector, node)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def autocorrect(corrector, node)
|
52
|
+
corrector.replace(node, 'response.parsed_body')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -16,23 +16,15 @@ module RuboCop
|
|
16
16
|
#
|
17
17
|
# # good
|
18
18
|
# def change
|
19
|
-
#
|
20
|
-
# t.
|
19
|
+
# change_table :users do |t|
|
20
|
+
# t.remove :name, :string
|
21
21
|
# end
|
22
22
|
# end
|
23
23
|
#
|
24
24
|
# # good
|
25
25
|
# def change
|
26
|
-
#
|
27
|
-
#
|
28
|
-
# dir.up do
|
29
|
-
# t.column :name, :string
|
30
|
-
# end
|
31
|
-
#
|
32
|
-
# dir.down do
|
33
|
-
# t.remove :name
|
34
|
-
# end
|
35
|
-
# end
|
26
|
+
# create_table :users do |t|
|
27
|
+
# t.string :name
|
36
28
|
# end
|
37
29
|
# end
|
38
30
|
#
|
@@ -114,21 +106,6 @@ module RuboCop
|
|
114
106
|
# end
|
115
107
|
# end
|
116
108
|
#
|
117
|
-
# # good
|
118
|
-
# def change
|
119
|
-
# reversible do |dir|
|
120
|
-
# change_table :users do |t|
|
121
|
-
# dir.up do
|
122
|
-
# t.change :price, :string
|
123
|
-
# end
|
124
|
-
#
|
125
|
-
# dir.down do
|
126
|
-
# t.change :price, :integer
|
127
|
-
# end
|
128
|
-
# end
|
129
|
-
# end
|
130
|
-
# end
|
131
|
-
#
|
132
109
|
# @example
|
133
110
|
# # remove_columns
|
134
111
|
#
|
@@ -173,8 +150,6 @@ module RuboCop
|
|
173
150
|
# def change
|
174
151
|
# remove_index :users, column: :email
|
175
152
|
# end
|
176
|
-
#
|
177
|
-
# @see https://api.rubyonrails.org/classes/ActiveRecord/Migration/CommandRecorder.html
|
178
153
|
class ReversibleMigration < Base
|
179
154
|
include MigrationsHelper
|
180
155
|
|
@@ -186,11 +186,7 @@ module RuboCop
|
|
186
186
|
def build_path_glob_replacement(path, method)
|
187
187
|
receiver = range_between(path.loc.expression.begin_pos, path.children.first.loc.selector.end_pos).source
|
188
188
|
|
189
|
-
argument =
|
190
|
-
path.first_argument.source
|
191
|
-
else
|
192
|
-
join_arguments(path.arguments)
|
193
|
-
end
|
189
|
+
argument = path.arguments.one? ? path.first_argument.source : join_arguments(path.arguments)
|
194
190
|
|
195
191
|
"#{receiver}.#{method}(#{argument})"
|
196
192
|
end
|
@@ -214,11 +210,28 @@ module RuboCop
|
|
214
210
|
end
|
215
211
|
|
216
212
|
def join_arguments(arguments)
|
217
|
-
|
218
|
-
|
213
|
+
use_interpolation = false
|
214
|
+
|
215
|
+
joined_arguments = arguments.map do |arg|
|
216
|
+
if arg.respond_to?(:value)
|
217
|
+
arg.value
|
218
|
+
else
|
219
|
+
use_interpolation = true
|
220
|
+
"\#{#{arg.source}}"
|
221
|
+
end
|
222
|
+
end.join('/')
|
223
|
+
quote = enforce_double_quotes? || include_interpolation?(arguments) || use_interpolation ? '"' : "'"
|
219
224
|
|
220
225
|
"#{quote}#{joined_arguments}#{quote}"
|
221
226
|
end
|
227
|
+
|
228
|
+
def enforce_double_quotes?
|
229
|
+
string_literals_config['EnforcedStyle'] == 'double_quotes'
|
230
|
+
end
|
231
|
+
|
232
|
+
def string_literals_config
|
233
|
+
config.for_cop('Style/StringLiterals')
|
234
|
+
end
|
222
235
|
end
|
223
236
|
end
|
224
237
|
end
|
@@ -48,6 +48,7 @@ module RuboCop
|
|
48
48
|
SQL = 'SQL'
|
49
49
|
SQUISH = '.squish'
|
50
50
|
MSG = 'Use `%<expect>s` instead of `%<current>s`.'
|
51
|
+
SQL_IDENTIFIER_MARKERS = /(".+?")|('.+?')|(\[.+?\])/.freeze
|
51
52
|
|
52
53
|
def on_heredoc(node)
|
53
54
|
return unless offense_detected?(node)
|
@@ -60,7 +61,7 @@ module RuboCop
|
|
60
61
|
private
|
61
62
|
|
62
63
|
def offense_detected?(node)
|
63
|
-
sql_heredoc?(node) && !using_squish?(node)
|
64
|
+
sql_heredoc?(node) && !using_squish?(node) && !singleline_comments_present?(node)
|
64
65
|
end
|
65
66
|
|
66
67
|
def sql_heredoc?(node)
|
@@ -71,6 +72,12 @@ module RuboCop
|
|
71
72
|
node.parent&.send_type? && node.parent&.method?(:squish)
|
72
73
|
end
|
73
74
|
|
75
|
+
def singleline_comments_present?(node)
|
76
|
+
sql = node.children.map { |c| c.is_a?(String) ? c : c.source }.join('\n')
|
77
|
+
|
78
|
+
sql.gsub(SQL_IDENTIFIER_MARKERS, '').include?('--')
|
79
|
+
end
|
80
|
+
|
74
81
|
def message(node)
|
75
82
|
format(MSG, expect: "#{node.source}#{SQUISH}", current: node.source)
|
76
83
|
end
|
@@ -228,12 +228,25 @@ module RuboCop
|
|
228
228
|
acceptable
|
229
229
|
end
|
230
230
|
|
231
|
-
# Time.new can be called with a time zone offset
|
231
|
+
# Time.new, Time.at, and Time.now can be called with a time zone offset
|
232
232
|
# When it is, that should be considered safe
|
233
233
|
# Example:
|
234
234
|
# Time.new(1988, 3, 15, 3, 0, 0, "-05:00")
|
235
235
|
def offset_provided?(node)
|
236
|
-
node.
|
236
|
+
case node.method_name
|
237
|
+
when :new
|
238
|
+
node.arguments.size == 7 || offset_option_provided?(node)
|
239
|
+
when :at, :now
|
240
|
+
offset_option_provided?(node)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
def offset_option_provided?(node)
|
245
|
+
options = node.last_argument
|
246
|
+
options&.hash_type? &&
|
247
|
+
options.each_pair.any? do |pair|
|
248
|
+
pair.key.sym_type? && pair.key.value == :in && !pair.value.nil_type?
|
249
|
+
end
|
237
250
|
end
|
238
251
|
end
|
239
252
|
end
|
@@ -45,8 +45,6 @@ module RuboCop
|
|
45
45
|
# # Commit
|
46
46
|
# next if user.active?
|
47
47
|
# end
|
48
|
-
#
|
49
|
-
# @see https://github.com/rails/rails/commit/15aa4200e083
|
50
48
|
class TransactionExitStatement < Base
|
51
49
|
MSG = <<~MSG.chomp
|
52
50
|
Exit statement `%<statement>s` is not allowed. Use `raise` (rollback) or `next` (commit).
|
@@ -139,11 +139,20 @@ module RuboCop
|
|
139
139
|
pairs = node.arguments.last
|
140
140
|
return unless pairs.hash_type?
|
141
141
|
|
142
|
+
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?
|
146
|
+
|
147
|
+
condition_hash_part?(uniqueness_node, keys: %i[if unless conditions])
|
148
|
+
end
|
149
|
+
|
150
|
+
def condition_hash_part?(pairs, keys:)
|
142
151
|
pairs.each_pair.any? do |pair|
|
143
152
|
key = pair.key
|
144
153
|
next unless key.sym_type?
|
145
154
|
|
146
|
-
|
155
|
+
keys.include?(key.value)
|
147
156
|
end
|
148
157
|
end
|
149
158
|
|
@@ -28,12 +28,16 @@ module RuboCop
|
|
28
28
|
(send self :ignored_columns= $array)
|
29
29
|
PATTERN
|
30
30
|
|
31
|
+
def_node_matcher :appended_ignored_columns, <<~PATTERN
|
32
|
+
(op-asgn (send self :ignored_columns) :+ $array)
|
33
|
+
PATTERN
|
34
|
+
|
31
35
|
def_node_matcher :column_name, <<~PATTERN
|
32
36
|
({str sym} $_)
|
33
37
|
PATTERN
|
34
38
|
|
35
39
|
def on_send(node)
|
36
|
-
return unless (columns = ignored_columns(node))
|
40
|
+
return unless (columns = ignored_columns(node) || appended_ignored_columns(node))
|
37
41
|
return unless schema
|
38
42
|
|
39
43
|
table = table(node)
|
@@ -43,6 +47,7 @@ module RuboCop
|
|
43
47
|
check_column_existence(column_node, table)
|
44
48
|
end
|
45
49
|
end
|
50
|
+
alias on_op_asgn on_send
|
46
51
|
|
47
52
|
private
|
48
53
|
|
@@ -38,7 +38,9 @@ module RuboCop
|
|
38
38
|
def on_send(node)
|
39
39
|
return unless node.first_argument.sym_type?
|
40
40
|
|
41
|
-
|
41
|
+
root_receiver = root_receiver(node)
|
42
|
+
where_node_and_argument(root_receiver) do |where_node, where_argument|
|
43
|
+
next unless root_receiver == root_receiver(where_node)
|
42
44
|
next unless same_relationship?(where_argument, node.first_argument)
|
43
45
|
|
44
46
|
range = range_between(node.loc.selector.begin_pos, node.loc.expression.end_pos)
|
@@ -50,7 +52,12 @@ module RuboCop
|
|
50
52
|
private
|
51
53
|
|
52
54
|
def root_receiver(node)
|
53
|
-
|
55
|
+
parent = node.parent
|
56
|
+
if !parent&.send_type? || parent.method?(:or) || parent.method?(:and)
|
57
|
+
node
|
58
|
+
else
|
59
|
+
root_receiver(parent)
|
60
|
+
end
|
54
61
|
end
|
55
62
|
|
56
63
|
def same_relationship?(where, left_joins)
|
@@ -99,6 +99,7 @@ require_relative 'rails/render_inline'
|
|
99
99
|
require_relative 'rails/render_plain_text'
|
100
100
|
require_relative 'rails/request_referer'
|
101
101
|
require_relative 'rails/require_dependency'
|
102
|
+
require_relative 'rails/response_parsed_body'
|
102
103
|
require_relative 'rails/reversible_migration'
|
103
104
|
require_relative 'rails/reversible_migration_method_definition'
|
104
105
|
require_relative 'rails/root_join_chain'
|
data/lib/rubocop/rails.rb
CHANGED
@@ -5,7 +5,7 @@ module RuboCop
|
|
5
5
|
module Rails
|
6
6
|
PROJECT_ROOT = Pathname.new(__dir__).parent.parent.expand_path.freeze
|
7
7
|
CONFIG_DEFAULT = PROJECT_ROOT.join('config', 'default.yml').freeze
|
8
|
-
CONFIG = YAML.safe_load(CONFIG_DEFAULT.read).freeze
|
8
|
+
CONFIG = YAML.safe_load(CONFIG_DEFAULT.read, permitted_classes: [Regexp, Symbol]).freeze
|
9
9
|
|
10
10
|
private_constant(:CONFIG_DEFAULT, :PROJECT_ROOT)
|
11
11
|
|
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.18.0
|
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:
|
13
|
+
date: 2023-02-25 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -173,6 +173,7 @@ files:
|
|
173
173
|
- lib/rubocop/cop/rails/render_plain_text.rb
|
174
174
|
- lib/rubocop/cop/rails/request_referer.rb
|
175
175
|
- lib/rubocop/cop/rails/require_dependency.rb
|
176
|
+
- lib/rubocop/cop/rails/response_parsed_body.rb
|
176
177
|
- lib/rubocop/cop/rails/reversible_migration.rb
|
177
178
|
- lib/rubocop/cop/rails/reversible_migration_method_definition.rb
|
178
179
|
- lib/rubocop/cop/rails/root_join_chain.rb
|
@@ -217,7 +218,7 @@ metadata:
|
|
217
218
|
homepage_uri: https://docs.rubocop.org/rubocop-rails/
|
218
219
|
changelog_uri: https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md
|
219
220
|
source_code_uri: https://github.com/rubocop/rubocop-rails/
|
220
|
-
documentation_uri: https://docs.rubocop.org/rubocop-rails/2.
|
221
|
+
documentation_uri: https://docs.rubocop.org/rubocop-rails/2.18/
|
221
222
|
bug_tracker_uri: https://github.com/rubocop/rubocop-rails/issues
|
222
223
|
rubygems_mfa_required: 'true'
|
223
224
|
post_install_message:
|
@@ -235,7 +236,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
235
236
|
- !ruby/object:Gem::Version
|
236
237
|
version: '0'
|
237
238
|
requirements: []
|
238
|
-
rubygems_version: 3.
|
239
|
+
rubygems_version: 3.4.1
|
239
240
|
signing_key:
|
240
241
|
specification_version: 4
|
241
242
|
summary: Automatic Rails code style checking tool.
|