rubocop-rails 2.30.1 → 2.32.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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -1
  3. data/config/default.yml +63 -47
  4. data/lib/rubocop/cop/mixin/active_record_helper.rb +1 -1
  5. data/lib/rubocop/cop/mixin/active_record_migrations_helper.rb +2 -2
  6. data/lib/rubocop/cop/mixin/database_type_resolvable.rb +2 -2
  7. data/lib/rubocop/cop/mixin/enforce_superclass.rb +6 -1
  8. data/lib/rubocop/cop/mixin/index_method.rb +2 -1
  9. data/lib/rubocop/cop/rails/arel_star.rb +5 -5
  10. data/lib/rubocop/cop/rails/blank.rb +1 -1
  11. data/lib/rubocop/cop/rails/delegate.rb +10 -0
  12. data/lib/rubocop/cop/rails/eager_evaluation_log_message.rb +1 -3
  13. data/lib/rubocop/cop/rails/index_by.rb +9 -0
  14. data/lib/rubocop/cop/rails/index_with.rb +9 -0
  15. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +11 -1
  16. data/lib/rubocop/cop/rails/output.rb +1 -2
  17. data/lib/rubocop/cop/rails/pluck.rb +10 -4
  18. data/lib/rubocop/cop/rails/present.rb +1 -1
  19. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +6 -1
  20. data/lib/rubocop/cop/rails/reflection_class_name.rb +2 -2
  21. data/lib/rubocop/cop/rails/relative_date_constant.rb +1 -1
  22. data/lib/rubocop/cop/rails/reversible_migration.rb +2 -1
  23. data/lib/rubocop/cop/rails/save_bang.rb +2 -2
  24. data/lib/rubocop/cop/rails/schema_comment.rb +1 -1
  25. data/lib/rubocop/cop/rails/three_state_boolean_column.rb +1 -1
  26. data/lib/rubocop/cop/rails/time_zone.rb +3 -1
  27. data/lib/rubocop/cop/rails/transaction_exit_statement.rb +2 -2
  28. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +10 -33
  29. data/lib/rubocop/rails/version.rb +1 -1
  30. data/lib/rubocop-rails.rb +0 -1
  31. metadata +7 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b27c710b734d026be33bd2bb2f777e58aa4b1bfbedbcfb487b9a900bcb3689d6
4
- data.tar.gz: d817c2bdda07d206ef7521122ed915859f820fe45c059740c885f7478d75bbfa
3
+ metadata.gz: '009a04a87f7692e278ce16b061ff93814ada6644691ce2fdd4ac4c7659e68c4d'
4
+ data.tar.gz: 313e26b30279cf9ebba24f5f99bc78b2b44433b24bc3522a6d4261de1cf72282
5
5
  SHA512:
6
- metadata.gz: bf49fe022c9885721fe7d5b0466052fbfbff90c3e421cc23d0abdb1f8f45e964e12aed5978202e7a9894c50c82cc4df3ce686a74735df80255628db05136df26
7
- data.tar.gz: 8117361c6ae1e240c8994c482810278e5d157316ed3b01416630b0c3ee868ebac02c74e2c073a8e9d3958bcd04d849d9ae1f8ea90c0cc8289d8a136f3ab5e97d
6
+ metadata.gz: 1f7397609be46c75da8ff050ed1325db850c39df7d097d9faeb6984162b706ed92e203f151a30a68aa41b3af8fcdd63b7e76c51ebdcfe31980129a853d7cd8a3
7
+ data.tar.gz: 46006ebeb148838e1ae7f3dc56614b261fc90779c5e3772e163c9431034a89dbc614ef1cb1b913d5236fbc2b04708643fc27b593d8c0c4147898271c045cb4c7
data/README.md CHANGED
@@ -5,7 +5,8 @@
5
5
 
6
6
  A [RuboCop](https://github.com/rubocop/rubocop) extension focused on enforcing Rails best practices and coding conventions.
7
7
 
8
- Note: This repository manages rubocop-rails gem (>= 2.0.0). rubocop-rails gem (<= 1.5.0) has been renamed to [rubocop-rails_config](https://rubygems.org/gems/rubocop-rails_config) gem.
8
+ > [!IMPORTANT]
9
+ > This repository manages rubocop-rails gem (>= 2.0.0). rubocop-rails gem (<= 1.5.0) has been renamed to [rubocop-rails_config](https://rubygems.org/gems/rubocop-rails_config) gem.
9
10
 
10
11
  ## Installation
11
12
 
data/config/default.yml CHANGED
@@ -6,7 +6,7 @@ inherit_mode:
6
6
 
7
7
  AllCops:
8
8
  Exclude:
9
- - app/assets/**/*
9
+ - '**/app/assets/**/*'
10
10
  - bin/*
11
11
  # Exclude db/schema.rb and db/[CONFIGURATION_NAMESPACE]_schema.rb by default.
12
12
  # See: https://guides.rubyonrails.org/active_record_multiple_databases.html#setting-up-your-application
@@ -77,6 +77,20 @@ Lint/SafeNavigationChain:
77
77
  - try!
78
78
  - in?
79
79
 
80
+ Lint/UselessAccessModifier:
81
+ # Add methods from `ActiveSupport::Concern` and `Module::Concerning`:
82
+ # https://api.rubyonrails.org/classes/ActiveSupport/Concern.html
83
+ # https://api.rubyonrails.org/classes/Module/Concerning
84
+ inherit_mode:
85
+ merge:
86
+ - ContextCreatingMethods
87
+ ContextCreatingMethods:
88
+ - class_methods
89
+ - included
90
+ - prepended
91
+ - concern
92
+ - concerning
93
+
80
94
  Rails:
81
95
  Enabled: true
82
96
  DocumentationBaseURL: https://docs.rubocop.org/rubocop-rails
@@ -107,8 +121,8 @@ Rails/ActionFilter:
107
121
  - action
108
122
  - filter
109
123
  Include:
110
- - app/controllers/**/*.rb
111
- - app/mailers/**/*.rb
124
+ - '**/app/controllers/**/*.rb'
125
+ - '**/app/mailers/**/*.rb'
112
126
 
113
127
  Rails/ActionOrder:
114
128
  Description: 'Enforce consistent ordering of controller actions.'
@@ -123,7 +137,7 @@ Rails/ActionOrder:
123
137
  - update
124
138
  - destroy
125
139
  Include:
126
- - app/controllers/**/*.rb
140
+ - '**/app/controllers/**/*.rb'
127
141
 
128
142
  Rails/ActiveRecordAliases:
129
143
  Description: >-
@@ -140,7 +154,7 @@ Rails/ActiveRecordCallbacksOrder:
140
154
  Enabled: 'pending'
141
155
  VersionAdded: '2.7'
142
156
  Include:
143
- - app/models/**/*.rb
157
+ - '**/app/models/**/*.rb'
144
158
 
145
159
  Rails/ActiveRecordOverride:
146
160
  Description: >-
@@ -151,7 +165,7 @@ Rails/ActiveRecordOverride:
151
165
  VersionAdded: '0.67'
152
166
  VersionChanged: '2.18'
153
167
  Include:
154
- - app/models/**/*.rb
168
+ - '**/app/models/**/*.rb'
155
169
 
156
170
  Rails/ActiveSupportAliases:
157
171
  Description: >-
@@ -238,7 +252,7 @@ Rails/AttributeDefaultBlockValue:
238
252
  Enabled: pending
239
253
  VersionAdded: '2.9'
240
254
  Include:
241
- - 'app/models/**/*'
255
+ - '**/app/models/**/*'
242
256
 
243
257
  Rails/BelongsTo:
244
258
  Description: >-
@@ -297,8 +311,8 @@ Rails/ContentTag:
297
311
  # https://puma.io/puma/Puma/DSL.html#tag-instance_method
298
312
  # No helpers are used in normal models and configs.
299
313
  Exclude:
300
- - app/models/**/*.rb
301
- - config/**/*.rb
314
+ - '**/app/models/**/*.rb'
315
+ - '**/config/**/*.rb'
302
316
 
303
317
  Rails/CreateTableWithTimestamps:
304
318
  Description: >-
@@ -353,11 +367,13 @@ Rails/Delegate:
353
367
  Description: 'Prefer delegate method for delegations.'
354
368
  Enabled: true
355
369
  VersionAdded: '0.21'
356
- VersionChanged: '0.50'
370
+ VersionChanged: '2.30'
357
371
  # When set to true, using the target object as a prefix of the
358
372
  # method name without using the `delegate` method will be a
359
373
  # violation. When set to false, this case is legal.
360
374
  EnforceForPrefixed: true
375
+ Exclude:
376
+ - '**/app/controllers/**/*.rb'
361
377
 
362
378
  Rails/DelegateAllowBlank:
363
379
  Description: 'Do not use allow_blank as an option to delegate.'
@@ -428,7 +444,7 @@ Rails/EnumHash:
428
444
  Enabled: true
429
445
  VersionAdded: '2.3'
430
446
  Include:
431
- - app/models/**/*.rb
447
+ - '**/app/models/**/*.rb'
432
448
 
433
449
  Rails/EnumSyntax:
434
450
  Description: 'Use positional arguments over keyword arguments when defining enums.'
@@ -436,14 +452,14 @@ Rails/EnumSyntax:
436
452
  Severity: warning
437
453
  VersionAdded: '2.26'
438
454
  Include:
439
- - app/models/**/*.rb
455
+ - '**/app/models/**/*.rb'
440
456
 
441
457
  Rails/EnumUniqueness:
442
458
  Description: 'Avoid duplicate integers in hash-syntax `enum` declaration.'
443
459
  Enabled: true
444
460
  VersionAdded: '0.46'
445
461
  Include:
446
- - app/models/**/*.rb
462
+ - '**/app/models/**/*.rb'
447
463
 
448
464
  Rails/EnvLocal:
449
465
  Description: 'Use `Rails.env.local?` instead of `Rails.env.development? || Rails.env.test?`.'
@@ -462,11 +478,11 @@ Rails/EnvironmentVariableAccess:
462
478
  VersionAdded: '2.10'
463
479
  VersionChanged: '2.24'
464
480
  Include:
465
- - app/**/*.rb
466
- - config/initializers/**/*.rb
467
- - lib/**/*.rb
481
+ - '**/app/**/*.rb'
482
+ - '**/config/initializers/**/*.rb'
483
+ - '**/lib/**/*.rb'
468
484
  Exclude:
469
- - lib/**/*.rake
485
+ - '**/lib/**/*.rake'
470
486
  AllowReads: false
471
487
  AllowWrites: false
472
488
 
@@ -478,11 +494,11 @@ Rails/Exit:
478
494
  Enabled: true
479
495
  VersionAdded: '0.41'
480
496
  Include:
481
- - app/**/*.rb
482
- - config/**/*.rb
483
- - lib/**/*.rb
497
+ - '**/app/**/*.rb'
498
+ - '**/config/**/*.rb'
499
+ - '**/lib/**/*.rb'
484
500
  Exclude:
485
- - lib/**/*.rake
501
+ - '**/lib/**/*.rake'
486
502
 
487
503
  Rails/ExpandedDateRange:
488
504
  Description: 'Checks for expanded date range.'
@@ -544,7 +560,7 @@ Rails/HasAndBelongsToMany:
544
560
  Enabled: true
545
561
  VersionAdded: '0.12'
546
562
  Include:
547
- - app/models/**/*.rb
563
+ - '**/app/models/**/*.rb'
548
564
 
549
565
  Rails/HasManyOrHasOneDependent:
550
566
  Description: 'Define the dependent option to the has_many and has_one associations.'
@@ -552,14 +568,14 @@ Rails/HasManyOrHasOneDependent:
552
568
  Enabled: true
553
569
  VersionAdded: '0.50'
554
570
  Include:
555
- - app/models/**/*.rb
571
+ - '**/app/models/**/*.rb'
556
572
 
557
573
  Rails/HelperInstanceVariable:
558
574
  Description: 'Do not use instance variables in helpers.'
559
575
  Enabled: true
560
576
  VersionAdded: '2.0'
561
577
  Include:
562
- - app/helpers/**/*.rb
578
+ - '**/app/helpers/**/*.rb'
563
579
 
564
580
  Rails/HttpPositionalArguments:
565
581
  Description: 'Use keyword arguments instead of positional arguments in http method calls.'
@@ -590,7 +606,7 @@ Rails/I18nLazyLookup:
590
606
  - lazy
591
607
  - explicit
592
608
  Include:
593
- - 'app/controllers/**/*.rb'
609
+ - '**/app/controllers/**/*.rb'
594
610
 
595
611
  Rails/I18nLocaleAssignment:
596
612
  Description: 'Prefer the usage of `I18n.with_locale` instead of manually updating `I18n.locale` value.'
@@ -619,8 +635,8 @@ Rails/IgnoredSkipActionFilterOption:
619
635
  Enabled: true
620
636
  VersionAdded: '0.63'
621
637
  Include:
622
- - app/controllers/**/*.rb
623
- - app/mailers/**/*.rb
638
+ - '**/app/controllers/**/*.rb'
639
+ - '**/app/mailers/**/*.rb'
624
640
 
625
641
  Rails/IndexBy:
626
642
  Description: 'Prefer `index_by` over `each_with_object`, `to_h`, or `map`.'
@@ -649,7 +665,7 @@ Rails/InverseOf:
649
665
  VersionAdded: '0.52'
650
666
  IgnoreScopes: false
651
667
  Include:
652
- - app/models/**/*.rb
668
+ - '**/app/models/**/*.rb'
653
669
 
654
670
  Rails/LexicallyScopedActionFilter:
655
671
  Description: "Checks that methods specified in the filter's `only` or `except` options are explicitly defined in the class."
@@ -658,8 +674,8 @@ Rails/LexicallyScopedActionFilter:
658
674
  Safe: false
659
675
  VersionAdded: '0.52'
660
676
  Include:
661
- - app/controllers/**/*.rb
662
- - app/mailers/**/*.rb
677
+ - '**/app/controllers/**/*.rb'
678
+ - '**/app/mailers/**/*.rb'
663
679
 
664
680
  Rails/LinkToBlank:
665
681
  Description: 'Checks that `link_to` with a `target: "_blank"` have a `rel: "noopener"` option passed to them.'
@@ -677,7 +693,7 @@ Rails/MailerName:
677
693
  SafeAutoCorrect: false
678
694
  VersionAdded: '2.7'
679
695
  Include:
680
- - app/mailers/**/*.rb
696
+ - '**/app/mailers/**/*.rb'
681
697
 
682
698
  Rails/MatchRoute:
683
699
  Description: >-
@@ -687,8 +703,8 @@ Rails/MatchRoute:
687
703
  Enabled: 'pending'
688
704
  VersionAdded: '2.7'
689
705
  Include:
690
- - config/routes.rb
691
- - config/routes/**/*.rb
706
+ - '**/config/routes.rb'
707
+ - '**/config/routes/**/*.rb'
692
708
 
693
709
  Rails/MigrationClassName:
694
710
  Description: 'The class name of the migration should match its file name.'
@@ -704,8 +720,8 @@ Rails/MultipleRoutePaths:
704
720
  Severity: warning
705
721
  VersionAdded: '2.29'
706
722
  Include:
707
- - config/routes.rb
708
- - config/routes/**/*.rb
723
+ - '**/config/routes.rb'
724
+ - '**/config/routes/**/*.rb'
709
725
 
710
726
  Rails/NegateInclude:
711
727
  Description: 'Prefer `collection.exclude?(obj)` over `!collection.include?(obj)`.'
@@ -741,10 +757,10 @@ Rails/Output:
741
757
  VersionAdded: '0.15'
742
758
  VersionChanged: '0.19'
743
759
  Include:
744
- - app/**/*.rb
745
- - config/**/*.rb
760
+ - '**/app/**/*.rb'
761
+ - '**/config/**/*.rb'
746
762
  - db/**/*.rb
747
- - lib/**/*.rb
763
+ - '**/lib/**/*.rb'
748
764
 
749
765
  Rails/OutputSafety:
750
766
  Description: 'The use of `html_safe` or `raw` may be a security risk.'
@@ -816,7 +832,7 @@ Rails/RakeEnvironment:
816
832
  - '**/Rakefile'
817
833
  - '**/*.rake'
818
834
  Exclude:
819
- - 'lib/capistrano/tasks/**/*.rake'
835
+ - '**/lib/capistrano/tasks/**/*.rake'
820
836
 
821
837
  Rails/ReadWriteAttribute:
822
838
  Description: >-
@@ -827,7 +843,7 @@ Rails/ReadWriteAttribute:
827
843
  VersionAdded: '0.20'
828
844
  VersionChanged: '0.29'
829
845
  Include:
830
- - app/models/**/*.rb
846
+ - '**/app/models/**/*.rb'
831
847
 
832
848
  Rails/RedundantActiveRecordAllMethod:
833
849
  Description: Detect redundant `all` used as a receiver for Active Record query methods.
@@ -846,7 +862,7 @@ Rails/RedundantAllowNil:
846
862
  Enabled: true
847
863
  VersionAdded: '0.67'
848
864
  Include:
849
- - app/models/**/*.rb
865
+ - '**/app/models/**/*.rb'
850
866
 
851
867
  Rails/RedundantForeignKey:
852
868
  Description: 'Checks for associations where the `:foreign_key` option is redundant.'
@@ -1017,7 +1033,7 @@ Rails/ScopeArgs:
1017
1033
  VersionAdded: '0.19'
1018
1034
  VersionChanged: '2.12'
1019
1035
  Include:
1020
- - app/models/**/*.rb
1036
+ - '**/app/models/**/*.rb'
1021
1037
 
1022
1038
  Rails/SelectMap:
1023
1039
  Description: 'Checks for uses of `select(:column_name)` with `map(&:column_name)`.'
@@ -1086,7 +1102,7 @@ Rails/StrongParametersExpect:
1086
1102
  Reference: 'https://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-expect'
1087
1103
  Enabled: pending
1088
1104
  Include:
1089
- - app/controllers/**/*.rb
1105
+ - '**/app/controllers/**/*.rb'
1090
1106
  SafeAutoCorrect: false
1091
1107
  VersionAdded: '2.29'
1092
1108
 
@@ -1097,7 +1113,7 @@ Rails/TableNameAssignment:
1097
1113
  Enabled: false
1098
1114
  VersionAdded: '2.14'
1099
1115
  Include:
1100
- - app/models/**/*.rb
1116
+ - '**/app/models/**/*.rb'
1101
1117
 
1102
1118
  Rails/ThreeStateBooleanColumn:
1103
1119
  Description: 'Add a default value and a `NOT NULL` constraint to boolean columns.'
@@ -1181,7 +1197,7 @@ Rails/UniqueValidationWithoutIndex:
1181
1197
  Enabled: true
1182
1198
  VersionAdded: '2.5'
1183
1199
  Include:
1184
- - app/models/**/*.rb
1200
+ - '**/app/models/**/*.rb'
1185
1201
 
1186
1202
  Rails/UnknownEnv:
1187
1203
  Description: 'Use correct environment name.'
@@ -1200,7 +1216,7 @@ Rails/UnusedIgnoredColumns:
1200
1216
  VersionAdded: '2.11'
1201
1217
  VersionChanged: '2.25'
1202
1218
  Include:
1203
- - app/models/**/*.rb
1219
+ - '**/app/models/**/*.rb'
1204
1220
 
1205
1221
  Rails/UnusedRenderContent:
1206
1222
  Description: 'Do not specify body content for a response with a non-content status code.'
@@ -1214,7 +1230,7 @@ Rails/Validation:
1214
1230
  VersionAdded: '0.9'
1215
1231
  VersionChanged: '0.41'
1216
1232
  Include:
1217
- - app/models/**/*.rb
1233
+ - '**/app/models/**/*.rb'
1218
1234
 
1219
1235
  Rails/WhereEquals:
1220
1236
  Description: 'Pass conditions to `where` and `where.not` as a hash instead of manually constructing SQL.'
@@ -103,7 +103,7 @@ module RuboCop
103
103
  end
104
104
 
105
105
  def in_where?(node)
106
- send_node = node.each_ancestor(:send, :csend).first
106
+ send_node = node.each_ancestor(:call).first
107
107
  return false unless send_node
108
108
 
109
109
  return true if WHERE_METHODS.include?(send_node.method_name)
@@ -22,9 +22,9 @@ module RuboCop
22
22
  ].freeze
23
23
 
24
24
  def_node_matcher :create_table_with_block?, <<~PATTERN
25
- (block
25
+ (any_block
26
26
  (send nil? :create_table ...)
27
- (args (arg _var))
27
+ { _ | (args (arg _var)) }
28
28
  _)
29
29
  PATTERN
30
30
  end
@@ -29,8 +29,8 @@ module RuboCop
29
29
  end
30
30
 
31
31
  def database_from_env
32
- url = ENV['DATABASE_URL'].presence
33
- return unless url
32
+ url = ENV.fetch('DATABASE_URL', '')
33
+ return if url.blank?
34
34
 
35
35
  case url
36
36
  when %r{\A(mysql2|trilogy)://}
@@ -1,7 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RuboCop
4
- module Cop
4
+ module Cop # rubocop:disable Style/Documentation
5
+ # The EnforceSuperclass module is also defined in `rubocop` (for backwards
6
+ # compatibility), so here we remove it before (re)defining it, to avoid
7
+ # warnings about methods in the module being redefined.
8
+ remove_const(:EnforceSuperclass) if defined?(EnforceSuperclass)
9
+
5
10
  # Common functionality for enforcing a specific superclass.
6
11
  module EnforceSuperclass
7
12
  def self.included(base)
@@ -58,7 +58,7 @@ module RuboCop
58
58
  end
59
59
 
60
60
  def set_new_arg_name(transformed_argname, corrector)
61
- return if block_node.numblock_type?
61
+ return unless block_node.block_type?
62
62
 
63
63
  corrector.replace(block_node.arguments, "|#{transformed_argname}|")
64
64
  end
@@ -84,6 +84,7 @@ module RuboCop
84
84
  end
85
85
 
86
86
  alias on_numblock on_block
87
+ alias on_itblock on_block
87
88
 
88
89
  def on_send(node)
89
90
  on_bad_map_to_h(node) do |*match|
@@ -5,14 +5,14 @@ module RuboCop
5
5
  module Rails
6
6
  # Prevents usage of `"*"` on an Arel::Table column reference.
7
7
  #
8
- # Using `arel_table["*"]` causes the outputted string to be a literal
9
- # quoted asterisk (e.g. <tt>`my_model`.`*`</tt>). This causes the
10
- # database to look for a column named <tt>`*`</tt> (or `"*"`) as opposed
8
+ # Using `arel_table["\*"]` causes the outputted string to be a literal
9
+ # quoted asterisk (e.g. `my_model`.`*`). This causes the
10
+ # database to look for a column named `\*` (or `"*"`) as opposed
11
11
  # to expanding the column list as one would likely expect.
12
12
  #
13
13
  # @safety
14
- # This cop's autocorrection is unsafe because it turns a quoted `*` into
15
- # an SQL `*`, unquoted. `*` is a valid column name in certain databases
14
+ # This cop's autocorrection is unsafe because it turns a quoted `\*` into
15
+ # an SQL `*`, unquoted. `\*` is a valid column name in certain databases
16
16
  # supported by Rails, and even though it is usually a mistake,
17
17
  # it might denote legitimate access to a column named `*`.
18
18
  #
@@ -123,7 +123,7 @@ module RuboCop
123
123
  def on_if(node)
124
124
  return unless cop_config['UnlessPresent']
125
125
  return unless node.unless?
126
- return if node.else? && config.for_cop('Style/UnlessElse')['Enabled']
126
+ return if node.else? && config.cop_enabled?('Style/UnlessElse')
127
127
 
128
128
  unless_present?(node) do |method_call, receiver|
129
129
  range = unless_condition(node, method_call)
@@ -15,6 +15,9 @@ module RuboCop
15
15
  # without using the `delegate` method will be a violation.
16
16
  # When set to `false`, this case is legal.
17
17
  #
18
+ # It is disabled for controllers in order to keep controller actions
19
+ # explicitly defined.
20
+ #
18
21
  # @example
19
22
  # # bad
20
23
  # def bar
@@ -74,6 +77,7 @@ module RuboCop
74
77
  def on_def(node)
75
78
  return unless trivial_delegate?(node)
76
79
  return if private_or_protected_delegation(node)
80
+ return if module_function_declared?(node)
77
81
 
78
82
  register_offense(node)
79
83
  end
@@ -163,6 +167,12 @@ module RuboCop
163
167
  private_or_protected_inline(node) || node_visibility(node) != :public
164
168
  end
165
169
 
170
+ def module_function_declared?(node)
171
+ node.each_ancestor(:module, :begin).any? do |ancestor|
172
+ ancestor.children.any? { |child| child.send_type? && child.method?(:module_function) }
173
+ end
174
+ end
175
+
166
176
  def private_or_protected_inline(node)
167
177
  processed_source[node.first_line - 1].strip.match?(/\A(private )|(protected )/)
168
178
  end
@@ -45,12 +45,10 @@ module RuboCop
45
45
  return if node.parent&.block_type?
46
46
 
47
47
  interpolated_string_passed_to_debug(node) do |arguments|
48
- message = format(MSG)
49
-
50
48
  range = replacement_range(node)
51
49
  replacement = replacement_source(node, arguments)
52
50
 
53
- add_offense(range, message: message) do |corrector|
51
+ add_offense(range) do |corrector|
54
52
  corrector.replace(range, replacement)
55
53
  end
56
54
  end
@@ -37,6 +37,9 @@ module RuboCop
37
37
  (numblock
38
38
  (call _ :to_h) $1
39
39
  (array $_ (lvar :_1)))
40
+ (itblock
41
+ (call _ :to_h) $:it
42
+ (array $_ (lvar :it)))
40
43
  }
41
44
  PATTERN
42
45
 
@@ -50,6 +53,9 @@ module RuboCop
50
53
  (numblock
51
54
  (call _ {:map :collect}) $1
52
55
  (array $_ (lvar :_1)))
56
+ (itblock
57
+ (call _ {:map :collect}) $:it
58
+ (array $_ (lvar :it)))
53
59
  }
54
60
  :to_h)
55
61
  PATTERN
@@ -66,6 +72,9 @@ module RuboCop
66
72
  (numblock
67
73
  (call _ {:map :collect}) $1
68
74
  (array $_ (lvar :_1)))
75
+ (itblock
76
+ (call _ {:map :collect}) $:it
77
+ (array $_ (lvar :it)))
69
78
  }
70
79
  )
71
80
  PATTERN
@@ -40,6 +40,9 @@ module RuboCop
40
40
  (numblock
41
41
  (call _ :to_h) $1
42
42
  (array (lvar :_1) $_))
43
+ (itblock
44
+ (call _ :to_h) $:it
45
+ (array (lvar :it) $_))
43
46
  }
44
47
  PATTERN
45
48
 
@@ -53,6 +56,9 @@ module RuboCop
53
56
  (numblock
54
57
  (call _ {:map :collect}) $1
55
58
  (array (lvar :_1) $_))
59
+ (itblock
60
+ (call _ {:map :collect}) $:it
61
+ (array (lvar :it) $_))
56
62
  }
57
63
  :to_h)
58
64
  PATTERN
@@ -69,6 +75,9 @@ module RuboCop
69
75
  (numblock
70
76
  (call _ {:map :collect}) $1
71
77
  (array (lvar :_1) $_))
78
+ (itblock
79
+ (call _ {:map :collect}) $:it
80
+ (array (lvar :it) $_))
72
81
  }
73
82
  )
74
83
  PATTERN
@@ -115,6 +115,10 @@ module RuboCop
115
115
  $_)))
116
116
  PATTERN
117
117
 
118
+ def_node_matcher :delegated_methods, <<~PATTERN
119
+ (send nil? :delegate (sym $_)+ (hash <(pair (sym :to) _) ...>))
120
+ PATTERN
121
+
118
122
  def on_send(node)
119
123
  methods_node = only_or_except_filter_methods(node)
120
124
  return unless methods_node
@@ -139,7 +143,13 @@ module RuboCop
139
143
  return [] unless block
140
144
 
141
145
  defined_methods = block.each_child_node(:def).map(&:method_name)
142
- defined_methods + aliased_action_methods(block, defined_methods)
146
+ defined_methods + delegated_action_methods(block) + aliased_action_methods(block, defined_methods)
147
+ end
148
+
149
+ def delegated_action_methods(node)
150
+ node.each_child_node(:send).flat_map do |child_node|
151
+ delegated_methods(child_node) || []
152
+ end
143
153
  end
144
154
 
145
155
  def aliased_action_methods(node, defined_methods)
@@ -23,7 +23,6 @@ module RuboCop
23
23
 
24
24
  MSG = "Do not write to stdout. Use Rails's logger if you want to log."
25
25
  RESTRICT_ON_SEND = %i[ap p pp pretty_print print puts binwrite syswrite write write_nonblock].freeze
26
- ALLOWED_TYPES = %i[send csend block numblock].freeze
27
26
 
28
27
  def_node_matcher :output?, <<~PATTERN
29
28
  (send nil? {:ap :p :pp :pretty_print :print :puts} ...)
@@ -40,7 +39,7 @@ module RuboCop
40
39
  PATTERN
41
40
 
42
41
  def on_send(node)
43
- return if ALLOWED_TYPES.include?(node.parent&.type)
42
+ return if node.parent&.call_type? || node.block_node
44
43
  return if !output?(node) && !io_output?(node)
45
44
 
46
45
  range = offense_range(node)
@@ -59,8 +59,9 @@ module RuboCop
59
59
  (any_block (call _ {:map :collect}) $_argument (send lvar :[] $_key))
60
60
  PATTERN
61
61
 
62
+ # rubocop:disable Metrics/AbcSize
62
63
  def on_block(node)
63
- return if node.each_ancestor(:block, :numblock).any?
64
+ return if node.each_ancestor(:any_block).any?
64
65
 
65
66
  pluck_candidate?(node) do |argument, key|
66
67
  next if key.regexp_type? || !use_one_block_argument?(argument)
@@ -68,20 +69,25 @@ module RuboCop
68
69
  match = if node.block_type?
69
70
  block_argument = argument.children.first.source
70
71
  use_block_argument_in_key?(block_argument, key)
71
- else # numblock
72
- argument == 1 && use_block_argument_in_key?('_1', key)
72
+ elsif node.numblock_type?
73
+ use_block_argument_in_key?('_1', key)
74
+ else # itblock
75
+ use_block_argument_in_key?('it', key)
73
76
  end
74
77
  next unless match
75
78
 
76
79
  register_offense(node, key)
77
80
  end
78
81
  end
82
+ # rubocop:enable Metrics/AbcSize
79
83
  alias on_numblock on_block
84
+ alias on_itblock on_block
80
85
 
81
86
  private
82
87
 
83
88
  def use_one_block_argument?(argument)
84
- return true if argument == 1 # Checks for numbered argument `_1`.
89
+ # Checks for numbered argument `_1` or `it block parameter.
90
+ return true if [1, :it].include?(argument)
85
91
 
86
92
  argument.respond_to?(:one?) && argument.one?
87
93
  end
@@ -110,7 +110,7 @@ module RuboCop
110
110
  def on_if(node)
111
111
  return unless cop_config['UnlessBlank']
112
112
  return unless node.unless?
113
- return if node.else? && config.for_cop('Style/UnlessElse')['Enabled']
113
+ return if node.else? && config.cop_enabled?('Style/UnlessElse')
114
114
 
115
115
  unless_blank?(node) do |method_call, receiver|
116
116
  range = unless_condition(node, method_call)
@@ -85,18 +85,22 @@ module RuboCop
85
85
  end
86
86
 
87
87
  alias on_numblock on_block
88
+ alias on_itblock on_block
88
89
 
89
90
  private
90
91
 
91
92
  def autocorrect(corrector, send_node, node)
92
93
  corrector.remove(send_node.receiver)
93
94
  corrector.remove(send_node.loc.dot)
94
- corrector.remove(block_argument_range(send_node)) unless node.numblock_type?
95
+ corrector.remove(block_argument_range(send_node)) if node.block_type?
95
96
  end
96
97
 
98
+ # rubocop:disable Metrics/AbcSize
97
99
  def redundant_receiver?(send_nodes, node)
98
100
  proc = if node.numblock_type?
99
101
  ->(n) { n.receiver.lvar_type? && n.receiver.source == '_1' }
102
+ elsif node.itblock_type?
103
+ ->(n) { n.receiver.lvar_type? && n.receiver.source == 'it' }
100
104
  else
101
105
  return false if node.arguments.empty?
102
106
 
@@ -106,6 +110,7 @@ module RuboCop
106
110
 
107
111
  send_nodes.all?(&proc)
108
112
  end
113
+ # rubocop:enable Metrics/AbcSize
109
114
 
110
115
  def block_argument_range(node)
111
116
  block_node = node.each_ancestor(:block).first
@@ -40,7 +40,7 @@ module RuboCop
40
40
 
41
41
  def on_send(node)
42
42
  association_with_reflection(node) do |reflection_class_name|
43
- return if reflection_class_name.value.send_type? && reflection_class_name.value.receiver.nil?
43
+ return if reflection_class_name.value.send_type? && !reflection_class_name.value.receiver&.const_type?
44
44
  return if reflection_class_name.value.lvar_type? && str_assigned?(reflection_class_name)
45
45
 
46
46
  add_offense(reflection_class_name) do |corrector|
@@ -76,7 +76,7 @@ module RuboCop
76
76
  def autocorrect(corrector, class_config)
77
77
  class_value = class_config.value
78
78
  replacement = const_or_string(class_value)
79
- return unless replacement.present?
79
+ return unless replacement
80
80
 
81
81
  corrector.replace(class_value, replacement.source.inspect)
82
82
  end
@@ -90,7 +90,7 @@ module RuboCop
90
90
  end
91
91
 
92
92
  def nested_relative_date(node, &callback)
93
- return if node.nil? || node.block_type?
93
+ return if node.nil? || node.any_block_type?
94
94
 
95
95
  node.each_child_node do |child|
96
96
  nested_relative_date(child, &callback)
@@ -205,6 +205,7 @@ module RuboCop
205
205
  end
206
206
 
207
207
  alias on_numblock on_block
208
+ alias on_itblock on_block
208
209
 
209
210
  private
210
211
 
@@ -218,7 +219,7 @@ module RuboCop
218
219
  return unless (last_argument = node.last_argument)
219
220
 
220
221
  drop_table_call(node) do
221
- unless node.parent.block_type? || last_argument.block_pass_type?
222
+ unless node.parent.any_block_type? || last_argument.block_pass_type?
222
223
  add_offense(node, message: format(MSG, action: 'drop_table(without block)'))
223
224
  end
224
225
  end
@@ -182,7 +182,7 @@ module RuboCop
182
182
  def right_assignment_node(assignment)
183
183
  node = assignment.node.child_nodes.first
184
184
 
185
- return node unless node&.block_type?
185
+ return node unless node&.any_block_type?
186
186
 
187
187
  node.send_node
188
188
  end
@@ -305,7 +305,7 @@ module RuboCop
305
305
 
306
306
  node = assignable_node(node)
307
307
  method, sibling_index = find_method_with_sibling_index(node.parent)
308
- return false unless method&.type?(:def, :block)
308
+ return false unless method&.type?(:def, :any_block)
309
309
 
310
310
  method.children.size == node.sibling_index + sibling_index
311
311
  end
@@ -39,7 +39,7 @@ module RuboCop
39
39
 
40
40
  # @!method comment_present?(node)
41
41
  def_node_matcher :comment_present?, <<~PATTERN
42
- (hash <(pair {(sym :comment) (str "comment")} (_ [present?])) ...>)
42
+ (hash <(pair {(sym :comment) (str "comment")} !{nil (str blank?)}) ...>)
43
43
  PATTERN
44
44
 
45
45
  # @!method add_column?(node)
@@ -45,7 +45,7 @@ module RuboCop
45
45
 
46
46
  return if required_options?(options_node)
47
47
 
48
- def_node = node.each_ancestor(:def, :defs).first
48
+ def_node = node.each_ancestor(:any_def).first
49
49
  table_node = table_node(node)
50
50
  return if def_node && (table_node.nil? || change_column_null?(def_node, table_node, column_node))
51
51
 
@@ -135,7 +135,9 @@ module RuboCop
135
135
  end
136
136
 
137
137
  def attach_timezone_specifier?(date)
138
- date.respond_to?(:value) && TIMEZONE_SPECIFIER.match?(date.value.to_s)
138
+ return false unless date.respond_to?(:value)
139
+
140
+ !date.value.to_s.valid_encoding? || TIMEZONE_SPECIFIER.match?(date.value.to_s)
139
141
  end
140
142
 
141
143
  def build_message(klass, method_name, node)
@@ -99,7 +99,7 @@ module RuboCop
99
99
  return false unless transaction_method_name?(node.method_name)
100
100
  return false unless (parent = node.parent)
101
101
 
102
- parent.block_type? && parent.body
102
+ parent.any_block_type? && parent.body
103
103
  end
104
104
 
105
105
  def statement(statement_node)
@@ -113,7 +113,7 @@ module RuboCop
113
113
  end
114
114
 
115
115
  def nested_block?(statement_node)
116
- name = statement_node.ancestors.find(&:block_type?).children.first.method_name
116
+ name = statement_node.ancestors.find(&:any_block_type?).children.first.method_name
117
117
  !transaction_method_name?(name)
118
118
  end
119
119
 
@@ -51,51 +51,28 @@ module RuboCop
51
51
 
52
52
  MSG = 'Use `distinct` before `pluck`.'
53
53
  RESTRICT_ON_SEND = %i[uniq].freeze
54
- NEWLINE = "\n"
55
- PATTERN = '[!^block (send (send %<type>s :pluck ...) :uniq ...)]'
56
54
 
57
- def_node_matcher :conservative_node_match, format(PATTERN, type: 'const')
58
-
59
- def_node_matcher :aggressive_node_match, format(PATTERN, type: '_')
55
+ def_node_matcher :uniq_before_pluck, '[!^any_block $(send $(send _ :pluck ...) :uniq ...)]'
60
56
 
61
57
  def on_send(node)
62
- uniq = if style == :conservative
63
- conservative_node_match(node)
64
- else
65
- aggressive_node_match(node)
66
- end
67
-
68
- return unless uniq
58
+ uniq_before_pluck(node) do |uniq_node, pluck_node|
59
+ next if style == :conservative && !pluck_node.receiver&.const_type?
69
60
 
70
- add_offense(node.loc.selector) do |corrector|
71
- autocorrect(corrector, node)
61
+ add_offense(uniq_node.loc.selector) do |corrector|
62
+ autocorrect(corrector, uniq_node, pluck_node)
63
+ end
72
64
  end
73
65
  end
74
66
 
75
67
  private
76
68
 
77
- def autocorrect(corrector, node)
78
- method = node.method_name
69
+ def autocorrect(corrector, uniq_node, pluck_node)
70
+ corrector.remove(range_between(pluck_node.loc.end.end_pos, uniq_node.loc.selector.end_pos))
79
71
 
80
- corrector.remove(dot_method_with_whitespace(method, node))
81
- if (dot = node.receiver.loc.dot)
72
+ if (dot = pluck_node.loc.dot)
82
73
  corrector.insert_before(dot.begin, '.distinct')
83
74
  else
84
- corrector.insert_before(node.receiver, 'distinct.')
85
- end
86
- end
87
-
88
- def dot_method_with_whitespace(method, node)
89
- range_between(dot_method_begin_pos(method, node), node.loc.selector.end_pos)
90
- end
91
-
92
- def dot_method_begin_pos(method, node)
93
- lines = node.source.split(NEWLINE)
94
-
95
- if lines.last.strip == ".#{method}"
96
- node.source.rindex(NEWLINE)
97
- else
98
- node.loc.dot.begin_pos
75
+ corrector.insert_before(pluck_node, 'distinct.')
99
76
  end
100
77
  end
101
78
  end
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Rails
5
5
  # This module holds the RuboCop Rails version information.
6
6
  module Version
7
- STRING = '2.30.1'
7
+ STRING = '2.32.0'
8
8
 
9
9
  def self.document_version
10
10
  STRING.match('\d+\.\d+').to_s
data/lib/rubocop-rails.rb CHANGED
@@ -3,7 +3,6 @@
3
3
  require 'rubocop'
4
4
  require 'rack/utils'
5
5
  require 'active_support/inflector'
6
- require 'active_support/core_ext/object/blank'
7
6
 
8
7
  require_relative 'rubocop/rails'
9
8
  require_relative 'rubocop/rails/version'
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.30.1
4
+ version: 2.32.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -9,7 +9,7 @@ authors:
9
9
  - Yuji Nakayama
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2025-02-17 00:00:00.000000000 Z
12
+ date: 2025-05-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -59,7 +59,7 @@ dependencies:
59
59
  requirements:
60
60
  - - ">="
61
61
  - !ruby/object:Gem::Version
62
- version: 1.72.1
62
+ version: 1.75.0
63
63
  - - "<"
64
64
  - !ruby/object:Gem::Version
65
65
  version: '2.0'
@@ -69,7 +69,7 @@ dependencies:
69
69
  requirements:
70
70
  - - ">="
71
71
  - !ruby/object:Gem::Version
72
- version: 1.72.1
72
+ version: 1.75.0
73
73
  - - "<"
74
74
  - !ruby/object:Gem::Version
75
75
  version: '2.0'
@@ -79,7 +79,7 @@ dependencies:
79
79
  requirements:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: 1.38.0
82
+ version: 1.44.0
83
83
  - - "<"
84
84
  - !ruby/object:Gem::Version
85
85
  version: '2.0'
@@ -89,7 +89,7 @@ dependencies:
89
89
  requirements:
90
90
  - - ">="
91
91
  - !ruby/object:Gem::Version
92
- version: 1.38.0
92
+ version: 1.44.0
93
93
  - - "<"
94
94
  - !ruby/object:Gem::Version
95
95
  version: '2.0'
@@ -264,7 +264,7 @@ metadata:
264
264
  homepage_uri: https://docs.rubocop.org/rubocop-rails/
265
265
  changelog_uri: https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md
266
266
  source_code_uri: https://github.com/rubocop/rubocop-rails/
267
- documentation_uri: https://docs.rubocop.org/rubocop-rails/2.30/
267
+ documentation_uri: https://docs.rubocop.org/rubocop-rails/2.32/
268
268
  bug_tracker_uri: https://github.com/rubocop/rubocop-rails/issues
269
269
  rubygems_mfa_required: 'true'
270
270
  default_lint_roller_plugin: RuboCop::Rails::Plugin