rubocop-rails 2.25.0 → 2.29.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/README.md +52 -2
- data/config/default.yml +47 -9
- data/lib/rubocop/cop/mixin/index_method.rb +12 -5
- data/lib/rubocop/cop/mixin/routes_helper.rb +20 -0
- data/lib/rubocop/cop/mixin/target_rails_version.rb +3 -5
- data/lib/rubocop/cop/rails/action_order.rb +1 -5
- data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +1 -5
- data/lib/rubocop/cop/rails/add_column_index.rb +1 -0
- data/lib/rubocop/cop/rails/application_record.rb +4 -0
- data/lib/rubocop/cop/rails/bulk_change_table.rb +11 -4
- data/lib/rubocop/cop/rails/compact_blank.rb +29 -8
- data/lib/rubocop/cop/rails/dangerous_column_names.rb +2 -0
- data/lib/rubocop/cop/rails/date.rb +2 -2
- data/lib/rubocop/cop/rails/enum_hash.rb +31 -8
- data/lib/rubocop/cop/rails/enum_syntax.rb +130 -0
- data/lib/rubocop/cop/rails/enum_uniqueness.rb +29 -7
- data/lib/rubocop/cop/rails/env_local.rb +26 -3
- data/lib/rubocop/cop/rails/file_path.rb +4 -1
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +7 -0
- data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +1 -1
- data/lib/rubocop/cop/rails/index_by.rb +28 -12
- data/lib/rubocop/cop/rails/index_with.rb +28 -12
- data/lib/rubocop/cop/rails/link_to_blank.rb +2 -2
- data/lib/rubocop/cop/rails/match_route.rb +1 -9
- data/lib/rubocop/cop/rails/multiple_route_paths.rb +50 -0
- data/lib/rubocop/cop/rails/not_null_column.rb +8 -2
- data/lib/rubocop/cop/rails/pluck.rb +20 -0
- data/lib/rubocop/cop/rails/pluck_in_where.rb +17 -8
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +29 -15
- data/lib/rubocop/cop/rails/present.rb +0 -2
- data/lib/rubocop/cop/rails/redundant_active_record_all_method.rb +1 -30
- data/lib/rubocop/cop/rails/redundant_foreign_key.rb +1 -1
- data/lib/rubocop/cop/rails/redundant_presence_validation_on_belongs_to.rb +9 -0
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +1 -1
- data/lib/rubocop/cop/rails/reflection_class_name.rb +1 -1
- data/lib/rubocop/cop/rails/render_plain_text.rb +6 -3
- data/lib/rubocop/cop/rails/request_referer.rb +1 -1
- data/lib/rubocop/cop/rails/reversible_migration.rb +3 -1
- data/lib/rubocop/cop/rails/root_pathname_methods.rb +15 -11
- data/lib/rubocop/cop/rails/save_bang.rb +1 -1
- data/lib/rubocop/cop/rails/schema_comment.rb +1 -0
- data/lib/rubocop/cop/rails/select_map.rb +3 -2
- data/lib/rubocop/cop/rails/skips_model_validations.rb +7 -2
- data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +1 -1
- data/lib/rubocop/cop/rails/strong_parameters_expect.rb +104 -0
- data/lib/rubocop/cop/rails/three_state_boolean_column.rb +2 -1
- data/lib/rubocop/cop/rails/time_zone.rb +13 -6
- data/lib/rubocop/cop/rails/transaction_exit_statement.rb +5 -0
- data/lib/rubocop/cop/rails/validation.rb +4 -1
- data/lib/rubocop/cop/rails/where_equals.rb +28 -12
- data/lib/rubocop/cop/rails/where_not.rb +11 -6
- data/lib/rubocop/cop/rails/where_range.rb +89 -43
- data/lib/rubocop/cop/rails_cops.rb +4 -0
- data/lib/rubocop/rails/migration_file_skippable.rb +54 -0
- data/lib/rubocop/rails/schema_loader/schema.rb +1 -1
- data/lib/rubocop/rails/version.rb +1 -1
- data/lib/rubocop/rails.rb +0 -1
- data/lib/rubocop-rails.rb +3 -0
- metadata +11 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 210e46df0db68aeef5761f3afeeb86d62a52015be55190d3e6e1fd65368721be
|
4
|
+
data.tar.gz: 7ff2ef268227cf39cb23b0479a8cf19c4ecc2acdf62c18f8e1766756e5965119
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c84c5690318920b054525a7fc21ca4e0f067a2093757f7ff8182d429587c94898ba1ea1160893fe29e9a8ef9427f6cc076f613f283b5b857da0529fea7654a47
|
7
|
+
data.tar.gz: ca501a5661bcebf2a6769a8cba620c637872e17023ac19fe8f6415b5ff4305d735ead0d24c7ffaee46f24c6cbeb466fcffeebdfb9cd96836211ab446643fc2a7
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# RuboCop Rails
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/rubocop-rails)
|
4
|
-
[](https://github.com/rubocop/rubocop-rails/actions/workflows/test.yml)
|
5
5
|
|
6
6
|
A [RuboCop](https://github.com/rubocop/rubocop) extension focused on enforcing Rails best practices and coding conventions.
|
7
7
|
|
@@ -63,9 +63,45 @@ RuboCop::RakeTask.new do |task|
|
|
63
63
|
end
|
64
64
|
```
|
65
65
|
|
66
|
+
## RuboCop Rails configuration
|
67
|
+
|
68
|
+
The following settings specific to RuboCop Rails can be configured in `.rubocop.yml`.
|
69
|
+
|
70
|
+
### `AllCops: TargetRailsVersion`
|
71
|
+
|
72
|
+
What version of Rails is the inspected code using? If a value is specified
|
73
|
+
for `TargetRailsVersion` then it is used. Acceptable values are specified
|
74
|
+
as a float (e.g., 7.2); the patch version of Rails should not be included.
|
75
|
+
|
76
|
+
```yaml
|
77
|
+
AllCops:
|
78
|
+
TargetRailsVersion: 7.2
|
79
|
+
```
|
80
|
+
|
81
|
+
If `TargetRailsVersion` is not set, RuboCop will parse the Gemfile.lock or
|
82
|
+
gems.locked file to find the version of Rails that has been bound to the
|
83
|
+
application. If neither of those files exist, RuboCop will use Rails 5.0
|
84
|
+
as the default.
|
85
|
+
|
86
|
+
### `AllCops: MigratedSchemaVersion`
|
87
|
+
|
88
|
+
By specifying the `MigratedSchemaVersion` option, migration files that have already been run can be ignored.
|
89
|
+
When `MigratedSchemaVersion: '20241225000000'` is set, migration files lower than or equal to '20241225000000' will be ignored.
|
90
|
+
For example, to ignore db/migrate/20241225000000_create_articles.rb and earlier migrations you would configure it the following way:
|
91
|
+
|
92
|
+
```yaml
|
93
|
+
AllCops:
|
94
|
+
MigratedSchemaVersion: '20241225000000'
|
95
|
+
```
|
96
|
+
|
97
|
+
This prevents inspecting schema settings for already applied migration files.
|
98
|
+
Changing already applied migrations should be avoided because it can lead to the schema getting out of sync
|
99
|
+
between your local copy and what it actually is in production, depending on when `bin/rails db:migrate` was executed.
|
100
|
+
If you want to modify your schema to comply with the cops, you should instead create new migrations.
|
101
|
+
|
66
102
|
## Rails configuration tip
|
67
103
|
|
68
|
-
|
104
|
+
In Rails 6.1+, add the following `config.generators.after_generate` setting to
|
69
105
|
your `config/environments/development.rb` to apply RuboCop autocorrection to code generated by `bin/rails g`.
|
70
106
|
|
71
107
|
```ruby
|
@@ -84,6 +120,20 @@ It uses `rubocop -A` to apply `Style/FrozenStringLiteralComment` and other unsaf
|
|
84
120
|
`rubocop -A` is unsafe autocorrection, but code generated by default is simple and less likely to
|
85
121
|
be incompatible with `rubocop -A`. If you have problems you can replace it with `rubocop -a` instead.
|
86
122
|
|
123
|
+
In Rails 7.2+, it is recommended to use `config.generators.apply_rubocop_autocorrect_after_generate!` instead of the above setting:
|
124
|
+
|
125
|
+
```diff
|
126
|
+
# config/environments/development.rb
|
127
|
+
Rails.application.configure do
|
128
|
+
(snip)
|
129
|
+
# Apply autocorrection by RuboCop to files generated by `bin/rails generate`.
|
130
|
+
- # config.generators.apply_rubocop_autocorrect_after_generate!
|
131
|
+
+ config.generators.apply_rubocop_autocorrect_after_generate!
|
132
|
+
end
|
133
|
+
```
|
134
|
+
|
135
|
+
You only need to uncomment.
|
136
|
+
|
87
137
|
## The Cops
|
88
138
|
|
89
139
|
All cops are located under
|
data/config/default.yml
CHANGED
@@ -17,14 +17,18 @@ AllCops:
|
|
17
17
|
# Enable checking Active Support extensions.
|
18
18
|
# See: https://docs.rubocop.org/rubocop/configuration.html#enable-checking-active-support-extensions
|
19
19
|
ActiveSupportExtensionsEnabled: true
|
20
|
-
# What version of Rails is the inspected code using?
|
21
|
-
# for TargetRailsVersion then it is used.
|
22
|
-
# as a float (
|
23
|
-
# If TargetRailsVersion is not set, RuboCop will parse the Gemfile.lock or
|
20
|
+
# What version of Rails is the inspected code using? If a value is specified
|
21
|
+
# for `TargetRailsVersion` then it is used. Acceptable values are specified
|
22
|
+
# as a float (e.g., 7.2); the patch version of Rails should not be included.
|
23
|
+
# If `TargetRailsVersion` is not set, RuboCop will parse the Gemfile.lock or
|
24
24
|
# gems.locked file to find the version of Rails that has been bound to the
|
25
|
-
# application.
|
25
|
+
# application. If neither of those files exist, RuboCop will use Rails 5.0
|
26
26
|
# as the default.
|
27
27
|
TargetRailsVersion: ~
|
28
|
+
# By specifying `MigratedSchemaVersion` option, migration files that have been migrated can be ignored.
|
29
|
+
# When `MigratedSchemaVersion: '20241231000000'` is set. Migration files lower than or equal to '20250101000000' will be ignored.
|
30
|
+
# For example, this is the timestamp in db/migrate/20250101000000_create_articles.rb.
|
31
|
+
MigratedSchemaVersion: ~
|
28
32
|
|
29
33
|
Lint/NumberConversion:
|
30
34
|
# Add Rails' duration methods to the ignore list for `Lint/NumberConversion`
|
@@ -212,7 +216,9 @@ Rails/ApplicationRecord:
|
|
212
216
|
Enabled: true
|
213
217
|
SafeAutoCorrect: false
|
214
218
|
VersionAdded: '0.49'
|
215
|
-
VersionChanged: '2.
|
219
|
+
VersionChanged: '2.26'
|
220
|
+
Exclude:
|
221
|
+
- db/**/*.rb
|
216
222
|
|
217
223
|
Rails/ArelStar:
|
218
224
|
Description: 'Enforces `Arel.star` instead of `"*"` for expanded columns.'
|
@@ -424,6 +430,14 @@ Rails/EnumHash:
|
|
424
430
|
Include:
|
425
431
|
- app/models/**/*.rb
|
426
432
|
|
433
|
+
Rails/EnumSyntax:
|
434
|
+
Description: 'Use positional arguments over keyword arguments when defining enums.'
|
435
|
+
Enabled: pending
|
436
|
+
Severity: warning
|
437
|
+
VersionAdded: '2.26'
|
438
|
+
Include:
|
439
|
+
- app/models/**/*.rb
|
440
|
+
|
427
441
|
Rails/EnumUniqueness:
|
428
442
|
Description: 'Avoid duplicate integers in hash-syntax `enum` declaration.'
|
429
443
|
Enabled: true
|
@@ -684,6 +698,15 @@ Rails/MigrationClassName:
|
|
684
698
|
Include:
|
685
699
|
- db/**/*.rb
|
686
700
|
|
701
|
+
Rails/MultipleRoutePaths:
|
702
|
+
Description: 'Checks for mapping a route with multiple paths, which is deprecated and will be removed in Rails 8.1.'
|
703
|
+
Enabled: pending
|
704
|
+
Severity: warning
|
705
|
+
VersionAdded: '2.29'
|
706
|
+
Include:
|
707
|
+
- config/routes.rb
|
708
|
+
- config/routes/**/*.rb
|
709
|
+
|
687
710
|
Rails/NegateInclude:
|
688
711
|
Description: 'Prefer `collection.exclude?(obj)` over `!collection.include?(obj)`.'
|
689
712
|
StyleGuide: 'https://rails.rubystyle.guide#exclude'
|
@@ -1018,8 +1041,9 @@ Rails/SkipsModelValidations:
|
|
1018
1041
|
See reference for more information.
|
1019
1042
|
Reference: 'https://guides.rubyonrails.org/active_record_validations.html#skipping-validations'
|
1020
1043
|
Enabled: true
|
1044
|
+
Safe: false
|
1021
1045
|
VersionAdded: '0.47'
|
1022
|
-
VersionChanged: '2.
|
1046
|
+
VersionChanged: '2.25'
|
1023
1047
|
ForbiddenMethods:
|
1024
1048
|
- decrement!
|
1025
1049
|
- decrement_counter
|
@@ -1057,6 +1081,15 @@ Rails/StripHeredoc:
|
|
1057
1081
|
Enabled: pending
|
1058
1082
|
VersionAdded: '2.15'
|
1059
1083
|
|
1084
|
+
Rails/StrongParametersExpect:
|
1085
|
+
Description: 'Enforces the use of `ActionController::Parameters#expect` as a method for strong parameter handling.'
|
1086
|
+
Reference: 'https://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-expect'
|
1087
|
+
Enabled: pending
|
1088
|
+
Include:
|
1089
|
+
- app/controllers/**/*.rb
|
1090
|
+
SafeAutoCorrect: false
|
1091
|
+
VersionAdded: '2.29'
|
1092
|
+
|
1060
1093
|
Rails/TableNameAssignment:
|
1061
1094
|
Description: >-
|
1062
1095
|
Do not use `self.table_name =`. Use Inflections or `table_name_prefix` instead.
|
@@ -1184,12 +1217,12 @@ Rails/Validation:
|
|
1184
1217
|
- app/models/**/*.rb
|
1185
1218
|
|
1186
1219
|
Rails/WhereEquals:
|
1187
|
-
Description: 'Pass conditions to `where` as a hash instead of manually constructing SQL.'
|
1220
|
+
Description: 'Pass conditions to `where` and `where.not` as a hash instead of manually constructing SQL.'
|
1188
1221
|
StyleGuide: 'https://rails.rubystyle.guide/#hash-conditions'
|
1189
1222
|
Enabled: 'pending'
|
1190
1223
|
SafeAutoCorrect: false
|
1191
1224
|
VersionAdded: '2.9'
|
1192
|
-
VersionChanged: '2.
|
1225
|
+
VersionChanged: '2.26'
|
1193
1226
|
|
1194
1227
|
Rails/WhereExists:
|
1195
1228
|
Description: 'Prefer `exists?(...)` over `where(...).exists?`.'
|
@@ -1226,12 +1259,17 @@ Rails/WhereRange:
|
|
1226
1259
|
Description: 'Use ranges in `where` instead of manually constructing SQL.'
|
1227
1260
|
StyleGuide: 'https://rails.rubystyle.guide/#where-ranges'
|
1228
1261
|
Enabled: pending
|
1262
|
+
SafeAutoCorrect: false
|
1229
1263
|
VersionAdded: '2.25'
|
1230
1264
|
|
1231
1265
|
# Accept `redirect_to(...) and return` and similar cases.
|
1232
1266
|
Style/AndOr:
|
1233
1267
|
EnforcedStyle: conditionals
|
1234
1268
|
|
1269
|
+
Style/CollectionCompact:
|
1270
|
+
AllowedReceivers:
|
1271
|
+
- params
|
1272
|
+
|
1235
1273
|
Style/FormatStringToken:
|
1236
1274
|
AllowedMethods:
|
1237
1275
|
- redirect
|
@@ -6,7 +6,7 @@ module RuboCop
|
|
6
6
|
module IndexMethod # rubocop:disable Metrics/ModuleLength
|
7
7
|
RESTRICT_ON_SEND = %i[each_with_object to_h map collect []].freeze
|
8
8
|
|
9
|
-
def on_block(node)
|
9
|
+
def on_block(node)
|
10
10
|
on_bad_each_with_object(node) do |*match|
|
11
11
|
handle_possible_offense(node, match, 'each_with_object')
|
12
12
|
end
|
@@ -18,6 +18,8 @@ module RuboCop
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
+
alias on_numblock on_block
|
22
|
+
|
21
23
|
def on_send(node)
|
22
24
|
on_bad_map_to_h(node) do |*match|
|
23
25
|
handle_possible_offense(node, match, 'map { ... }.to_h')
|
@@ -122,9 +124,9 @@ module RuboCop
|
|
122
124
|
end
|
123
125
|
|
124
126
|
def self.from_map_to_h(node, match)
|
125
|
-
|
126
|
-
|
127
|
-
|
127
|
+
if node.block_literal?
|
128
|
+
strip_trailing_chars = 0
|
129
|
+
else
|
128
130
|
map_range = node.children.first.source_range
|
129
131
|
node_range = node.source_range
|
130
132
|
strip_trailing_chars = node_range.end_pos - map_range.end_pos
|
@@ -153,11 +155,16 @@ module RuboCop
|
|
153
155
|
end
|
154
156
|
|
155
157
|
def set_new_arg_name(transformed_argname, corrector)
|
158
|
+
return if block_node.numblock_type?
|
159
|
+
|
156
160
|
corrector.replace(block_node.arguments, "|#{transformed_argname}|")
|
157
161
|
end
|
158
162
|
|
159
163
|
def set_new_body_expression(transforming_body_expr, corrector)
|
160
|
-
|
164
|
+
body_source = transforming_body_expr.source
|
165
|
+
body_source = "{ #{body_source} }" if transforming_body_expr.hash_type? && !transforming_body_expr.braces?
|
166
|
+
|
167
|
+
corrector.replace(block_node.body, body_source)
|
161
168
|
end
|
162
169
|
end
|
163
170
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# Common functionality for cops working with routes.
|
6
|
+
module RoutesHelper
|
7
|
+
extend NodePattern::Macros
|
8
|
+
|
9
|
+
HTTP_METHODS = %i[get post put patch delete].freeze
|
10
|
+
|
11
|
+
def_node_matcher :routes_draw?, <<~PATTERN
|
12
|
+
(send (send _ :routes) :draw)
|
13
|
+
PATTERN
|
14
|
+
|
15
|
+
def within_routes?(node)
|
16
|
+
node.each_ancestor(:block).any? { |block| routes_draw?(block.send_node) }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -7,6 +7,9 @@ module RuboCop
|
|
7
7
|
# Informs the base RuboCop gem that it the Rails version is checked via `requires_gem` API,
|
8
8
|
# without needing to call this `#support_target_rails_version` method.
|
9
9
|
USES_REQUIRES_GEM_API = true
|
10
|
+
# Look for `railties` instead of `rails`, to support apps that only use a subset of `rails`
|
11
|
+
# See https://github.com/rubocop/rubocop/pull/11289
|
12
|
+
TARGET_GEM_NAME = 'railties' # :nodoc:
|
10
13
|
|
11
14
|
def minimum_target_rails_version(version)
|
12
15
|
if respond_to?(:requires_gem)
|
@@ -33,11 +36,6 @@ module RuboCop
|
|
33
36
|
@minimum_target_rails_version <= version
|
34
37
|
end
|
35
38
|
end
|
36
|
-
|
37
|
-
# Look for `railties` instead of `rails`, to support apps that only use a subset of `rails`
|
38
|
-
# See https://github.com/rubocop/rubocop/pull/11289
|
39
|
-
TARGET_GEM_NAME = 'railties'
|
40
|
-
private_constant :TARGET_GEM_NAME
|
41
39
|
end
|
42
40
|
end
|
43
41
|
end
|
@@ -92,11 +92,7 @@ module RuboCop
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def range_with_comments(node)
|
95
|
-
|
96
|
-
# Using `RuboCop::Ext::Comment#source_range` requires RuboCop > 1.46,
|
97
|
-
# which introduces https://github.com/rubocop/rubocop/pull/11630.
|
98
|
-
ranges = [node, *processed_source.ast_with_comments[node]].map { |comment| comment.loc.expression }
|
99
|
-
# rubocop:enable InternalAffairs/LocationExpression
|
95
|
+
ranges = [node, *processed_source.ast_with_comments[node]].map(&:source_range)
|
100
96
|
ranges.reduce do |result, range|
|
101
97
|
add_range(result, range)
|
102
98
|
end
|
@@ -123,11 +123,7 @@ module RuboCop
|
|
123
123
|
end
|
124
124
|
|
125
125
|
def inline_comment?(comment)
|
126
|
-
|
127
|
-
# Using `RuboCop::Ext::Comment#source_range` requires RuboCop > 1.46,
|
128
|
-
# which introduces https://github.com/rubocop/rubocop/pull/11630.
|
129
|
-
!comment_line?(comment.loc.expression.source_line)
|
130
|
-
# rubocop:enable InternalAffairs/LocationExpression
|
126
|
+
!comment_line?(comment.source_range.source_line)
|
131
127
|
end
|
132
128
|
|
133
129
|
def start_line_position(node)
|
@@ -5,6 +5,10 @@ module RuboCop
|
|
5
5
|
module Rails
|
6
6
|
# Checks that models subclass `ApplicationRecord` with Rails 5.0.
|
7
7
|
#
|
8
|
+
# It is a common practice to define models inside migrations in order to retain forward
|
9
|
+
# compatibility by avoiding loading any application code. And so migration files are excluded
|
10
|
+
# by default for this cop.
|
11
|
+
#
|
8
12
|
# @safety
|
9
13
|
# This cop's autocorrection is unsafe because it may let the logic from `ApplicationRecord`
|
10
14
|
# sneak into an Active Record model that is not purposed to inherit logic common among other
|
@@ -65,6 +65,7 @@ module RuboCop
|
|
65
65
|
# end
|
66
66
|
class BulkChangeTable < Base
|
67
67
|
include DatabaseTypeResolvable
|
68
|
+
include MigrationsHelper
|
68
69
|
|
69
70
|
MSG_FOR_CHANGE_TABLE = <<~MSG.chomp
|
70
71
|
You can combine alter queries using `bulk: true` options.
|
@@ -113,8 +114,10 @@ module RuboCop
|
|
113
114
|
MYSQL_COMBINABLE_ALTER_METHODS = %i[rename_column add_index remove_index].freeze
|
114
115
|
|
115
116
|
POSTGRESQL_COMBINABLE_TRANSFORMATIONS = %i[change_default].freeze
|
117
|
+
POSTGRESQL_COMBINABLE_TRANSFORMATIONS_SINCE_6_1 = %i[change_null].freeze
|
116
118
|
|
117
119
|
POSTGRESQL_COMBINABLE_ALTER_METHODS = %i[change_column_default].freeze
|
120
|
+
POSTGRESQL_COMBINABLE_ALTER_METHODS_SINCE_6_1 = %i[change_column_null].freeze
|
118
121
|
|
119
122
|
def on_def(node)
|
120
123
|
return unless support_bulk_alter?
|
@@ -138,9 +141,9 @@ module RuboCop
|
|
138
141
|
return unless support_bulk_alter?
|
139
142
|
return unless node.command?(:change_table)
|
140
143
|
return if include_bulk_options?(node)
|
141
|
-
return unless node.block_node
|
144
|
+
return unless (body = node.block_node&.body)
|
142
145
|
|
143
|
-
send_nodes = send_nodes_from_change_table_block(
|
146
|
+
send_nodes = send_nodes_from_change_table_block(body)
|
144
147
|
|
145
148
|
add_offense_for_change_table(node) if count_transformations(send_nodes) > 1
|
146
149
|
end
|
@@ -196,7 +199,9 @@ module RuboCop
|
|
196
199
|
when MYSQL
|
197
200
|
COMBINABLE_ALTER_METHODS + MYSQL_COMBINABLE_ALTER_METHODS
|
198
201
|
when POSTGRESQL
|
199
|
-
COMBINABLE_ALTER_METHODS + POSTGRESQL_COMBINABLE_ALTER_METHODS
|
202
|
+
result = COMBINABLE_ALTER_METHODS + POSTGRESQL_COMBINABLE_ALTER_METHODS
|
203
|
+
result += POSTGRESQL_COMBINABLE_ALTER_METHODS_SINCE_6_1 if target_rails_version >= 6.1
|
204
|
+
result
|
200
205
|
end
|
201
206
|
end
|
202
207
|
|
@@ -205,7 +210,9 @@ module RuboCop
|
|
205
210
|
when MYSQL
|
206
211
|
COMBINABLE_TRANSFORMATIONS + MYSQL_COMBINABLE_TRANSFORMATIONS
|
207
212
|
when POSTGRESQL
|
208
|
-
COMBINABLE_TRANSFORMATIONS + POSTGRESQL_COMBINABLE_TRANSFORMATIONS
|
213
|
+
result = COMBINABLE_TRANSFORMATIONS + POSTGRESQL_COMBINABLE_TRANSFORMATIONS
|
214
|
+
result += POSTGRESQL_COMBINABLE_TRANSFORMATIONS_SINCE_6_1 if target_rails_version >= 6.1
|
215
|
+
result
|
209
216
|
end
|
210
217
|
end
|
211
218
|
|
@@ -16,7 +16,6 @@ module RuboCop
|
|
16
16
|
# And `compact_blank!` has different implementations for `Array`, `Hash`, and
|
17
17
|
# `ActionController::Parameters`.
|
18
18
|
# `Array#compact_blank!`, `Hash#compact_blank!` are equivalent to `delete_if(&:blank?)`.
|
19
|
-
# `ActionController::Parameters#compact_blank!` is equivalent to `reject!(&:blank?)`.
|
20
19
|
# If the cop makes a mistake, autocorrected code may get unexpected behavior.
|
21
20
|
#
|
22
21
|
# @example
|
@@ -24,6 +23,10 @@ module RuboCop
|
|
24
23
|
# # bad
|
25
24
|
# collection.reject(&:blank?)
|
26
25
|
# collection.reject { |_k, v| v.blank? }
|
26
|
+
# collection.select(&:present?)
|
27
|
+
# collection.select { |_k, v| v.present? }
|
28
|
+
# collection.filter(&:present?)
|
29
|
+
# collection.filter { |_k, v| v.present? }
|
27
30
|
#
|
28
31
|
# # good
|
29
32
|
# collection.compact_blank
|
@@ -31,8 +34,8 @@ module RuboCop
|
|
31
34
|
# # bad
|
32
35
|
# collection.delete_if(&:blank?) # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!`
|
33
36
|
# collection.delete_if { |_k, v| v.blank? } # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!`
|
34
|
-
# collection.
|
35
|
-
# collection.
|
37
|
+
# collection.keep_if(&:present?) # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!`
|
38
|
+
# collection.keep_if { |_k, v| v.present? } # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!`
|
36
39
|
#
|
37
40
|
# # good
|
38
41
|
# collection.compact_blank!
|
@@ -43,25 +46,41 @@ module RuboCop
|
|
43
46
|
extend TargetRailsVersion
|
44
47
|
|
45
48
|
MSG = 'Use `%<preferred_method>s` instead.'
|
46
|
-
RESTRICT_ON_SEND = %i[reject delete_if
|
49
|
+
RESTRICT_ON_SEND = %i[reject delete_if select filter keep_if].freeze
|
50
|
+
DESTRUCTIVE_METHODS = %i[delete_if keep_if].freeze
|
47
51
|
|
48
52
|
minimum_target_rails_version 6.1
|
49
53
|
|
50
54
|
def_node_matcher :reject_with_block?, <<~PATTERN
|
51
55
|
(block
|
52
|
-
(send _ {:reject :delete_if
|
56
|
+
(send _ {:reject :delete_if})
|
53
57
|
$(args ...)
|
54
58
|
(send
|
55
59
|
$(lvar _) :blank?))
|
56
60
|
PATTERN
|
57
61
|
|
58
62
|
def_node_matcher :reject_with_block_pass?, <<~PATTERN
|
59
|
-
(send _ {:reject :delete_if
|
63
|
+
(send _ {:reject :delete_if}
|
60
64
|
(block_pass
|
61
65
|
(sym :blank?)))
|
62
66
|
PATTERN
|
63
67
|
|
68
|
+
def_node_matcher :select_with_block?, <<~PATTERN
|
69
|
+
(block
|
70
|
+
(send _ {:select :filter :keep_if})
|
71
|
+
$(args ...)
|
72
|
+
(send
|
73
|
+
$(lvar _) :present?))
|
74
|
+
PATTERN
|
75
|
+
|
76
|
+
def_node_matcher :select_with_block_pass?, <<~PATTERN
|
77
|
+
(send _ {:select :filter :keep_if}
|
78
|
+
(block-pass
|
79
|
+
(sym :present?)))
|
80
|
+
PATTERN
|
81
|
+
|
64
82
|
def on_send(node)
|
83
|
+
return if target_ruby_version < 2.6 && node.method?(:filter)
|
65
84
|
return unless bad_method?(node)
|
66
85
|
|
67
86
|
range = offense_range(node)
|
@@ -75,8 +94,10 @@ module RuboCop
|
|
75
94
|
|
76
95
|
def bad_method?(node)
|
77
96
|
return true if reject_with_block_pass?(node)
|
97
|
+
return true if select_with_block_pass?(node)
|
78
98
|
|
79
|
-
|
99
|
+
arguments, receiver_in_block = reject_with_block?(node.parent) || select_with_block?(node.parent)
|
100
|
+
if arguments
|
80
101
|
return use_single_value_block_argument?(arguments, receiver_in_block) ||
|
81
102
|
use_hash_value_block_argument?(arguments, receiver_in_block)
|
82
103
|
end
|
@@ -103,7 +124,7 @@ module RuboCop
|
|
103
124
|
end
|
104
125
|
|
105
126
|
def preferred_method(node)
|
106
|
-
|
127
|
+
DESTRUCTIVE_METHODS.include?(node.method_name) ? 'compact_blank!' : 'compact_blank'
|
107
128
|
end
|
108
129
|
end
|
109
130
|
end
|
@@ -12,10 +12,10 @@ module RuboCop
|
|
12
12
|
# The cop also reports warnings when you are using `to_time` method,
|
13
13
|
# because it doesn't know about Rails time zone either.
|
14
14
|
#
|
15
|
-
# Two styles are supported for this cop. When `EnforcedStyle` is
|
15
|
+
# Two styles are supported for this cop. When `EnforcedStyle` is `strict`
|
16
16
|
# then the Date methods `today`, `current`, `yesterday`, and `tomorrow`
|
17
17
|
# are prohibited and the usage of both `to_time`
|
18
|
-
# and
|
18
|
+
# and `to_time_in_current_zone` are reported as warning.
|
19
19
|
#
|
20
20
|
# When `EnforcedStyle` is `flexible` then only `Date.today` is prohibited.
|
21
21
|
#
|
@@ -12,6 +12,12 @@ module RuboCop
|
|
12
12
|
#
|
13
13
|
# @example
|
14
14
|
# # bad
|
15
|
+
# enum :status, [:active, :archived]
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# enum :status, { active: 0, archived: 1 }
|
19
|
+
#
|
20
|
+
# # bad
|
15
21
|
# enum status: [:active, :archived]
|
16
22
|
#
|
17
23
|
# # good
|
@@ -23,7 +29,11 @@ module RuboCop
|
|
23
29
|
MSG = 'Enum defined as an array found in `%<enum>s` enum declaration. Use hash syntax instead.'
|
24
30
|
RESTRICT_ON_SEND = %i[enum].freeze
|
25
31
|
|
26
|
-
def_node_matcher :
|
32
|
+
def_node_matcher :enum_with_array?, <<~PATTERN
|
33
|
+
(send nil? :enum $_ ${array} ...)
|
34
|
+
PATTERN
|
35
|
+
|
36
|
+
def_node_matcher :enum_with_old_syntax?, <<~PATTERN
|
27
37
|
(send nil? :enum (hash $...))
|
28
38
|
PATTERN
|
29
39
|
|
@@ -32,17 +42,19 @@ module RuboCop
|
|
32
42
|
PATTERN
|
33
43
|
|
34
44
|
def on_send(node)
|
35
|
-
|
45
|
+
target_rails_version >= 7.0 && enum_with_array?(node) do |key, array|
|
46
|
+
add_offense(array, message: message(key)) do |corrector|
|
47
|
+
corrector.replace(array, build_hash(array))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
enum_with_old_syntax?(node) do |pairs|
|
36
52
|
pairs.each do |pair|
|
37
53
|
key, array = array_pair?(pair)
|
38
54
|
next unless key
|
39
55
|
|
40
|
-
add_offense(array, message:
|
41
|
-
|
42
|
-
"#{source(elem)} => #{index}"
|
43
|
-
end.join(', ')
|
44
|
-
|
45
|
-
corrector.replace(array, "{#{hash}}")
|
56
|
+
add_offense(array, message: message(key)) do |corrector|
|
57
|
+
corrector.replace(array, build_hash(array))
|
46
58
|
end
|
47
59
|
end
|
48
60
|
end
|
@@ -50,6 +62,10 @@ module RuboCop
|
|
50
62
|
|
51
63
|
private
|
52
64
|
|
65
|
+
def message(key)
|
66
|
+
format(MSG, enum: enum_name(key))
|
67
|
+
end
|
68
|
+
|
53
69
|
def enum_name(key)
|
54
70
|
case key.type
|
55
71
|
when :sym, :str
|
@@ -69,6 +85,13 @@ module RuboCop
|
|
69
85
|
elem.source
|
70
86
|
end
|
71
87
|
end
|
88
|
+
|
89
|
+
def build_hash(array)
|
90
|
+
hash = array.children.each_with_index.map do |elem, index|
|
91
|
+
"#{source(elem)} => #{index}"
|
92
|
+
end.join(', ')
|
93
|
+
"{#{hash}}"
|
94
|
+
end
|
72
95
|
end
|
73
96
|
end
|
74
97
|
end
|