rubocop-rails 2.25.1 → 2.26.2

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 (33) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -1
  3. data/config/default.yml +17 -3
  4. data/lib/rubocop/cop/rails/action_order.rb +1 -5
  5. data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +1 -5
  6. data/lib/rubocop/cop/rails/application_record.rb +4 -0
  7. data/lib/rubocop/cop/rails/bulk_change_table.rb +2 -2
  8. data/lib/rubocop/cop/rails/compact_blank.rb +29 -8
  9. data/lib/rubocop/cop/rails/date.rb +2 -2
  10. data/lib/rubocop/cop/rails/enum_hash.rb +31 -8
  11. data/lib/rubocop/cop/rails/enum_syntax.rb +128 -0
  12. data/lib/rubocop/cop/rails/enum_uniqueness.rb +29 -7
  13. data/lib/rubocop/cop/rails/file_path.rb +1 -1
  14. data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +1 -1
  15. data/lib/rubocop/cop/rails/pluck_in_where.rb +17 -8
  16. data/lib/rubocop/cop/rails/pluralization_grammar.rb +29 -15
  17. data/lib/rubocop/cop/rails/present.rb +0 -2
  18. data/lib/rubocop/cop/rails/redundant_active_record_all_method.rb +0 -29
  19. data/lib/rubocop/cop/rails/redundant_foreign_key.rb +1 -1
  20. data/lib/rubocop/cop/rails/redundant_presence_validation_on_belongs_to.rb +9 -0
  21. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +1 -1
  22. data/lib/rubocop/cop/rails/reflection_class_name.rb +1 -1
  23. data/lib/rubocop/cop/rails/render_plain_text.rb +6 -3
  24. data/lib/rubocop/cop/rails/request_referer.rb +1 -1
  25. data/lib/rubocop/cop/rails/root_pathname_methods.rb +15 -11
  26. data/lib/rubocop/cop/rails/skips_model_validations.rb +4 -2
  27. data/lib/rubocop/cop/rails/validation.rb +1 -1
  28. data/lib/rubocop/cop/rails/where_equals.rb +28 -12
  29. data/lib/rubocop/cop/rails/where_not.rb +11 -6
  30. data/lib/rubocop/cop/rails/where_range.rb +6 -1
  31. data/lib/rubocop/cop/rails_cops.rb +1 -0
  32. data/lib/rubocop/rails/version.rb +1 -1
  33. metadata +7 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b55703b258e4df9bae3a9a8c1b77a4fa143af6af3ed9b1b22118fd839d1ce06c
4
- data.tar.gz: 24568d7d8d22d69469ae9a4aaf426ea45bf848989604a8744ab6493bc0b222a3
3
+ metadata.gz: c6d480f2ef30bba709b183d1a3b71dee6c0838ea2815975b5fd25ab5933277ad
4
+ data.tar.gz: 1d36f2779e44e1fa03437154f388bf2e865c3af810e0238f5ddc6580f024fd04
5
5
  SHA512:
6
- metadata.gz: 47d5668b744967fc740b47552e9d05068fc5ce5c209a4a994a429262a0628b13e0f1e48d6a39018430fb7e874f88e4badbd9427219b9a77220e522d6706b1c3c
7
- data.tar.gz: 242030d6fe9063d51f18e98869e2a048a4b7b847f0f6a25937fc3d9781dbb7749de8b015b3fa0b4933511b83487ad060fbdbf9adb7942a20bfc035d5fc9e2f04
6
+ metadata.gz: 5cc2521c185293872667eb2a23aaaadc4ddee8289b1f16c9fff1e6c87b9498708226a0147697acb9bcc3be69642c3f3ecc063b749056c0df1cdb065a224e4a3d
7
+ data.tar.gz: ea268a009b987a6f61008602d67a8e89659611b7469fe6c1b9c81825b5f9227391035866b2ec593e6109e91a470d607f6f4bb48fd11155b9177d59daf2301111
data/README.md CHANGED
@@ -65,7 +65,7 @@ end
65
65
 
66
66
  ## Rails configuration tip
67
67
 
68
- If you are using Rails 6.1 or newer, add the following `config.generators.after_generate` setting to
68
+ In Rails 6.1+, add the following `config.generators.after_generate` setting to
69
69
  your `config/environments/development.rb` to apply RuboCop autocorrection to code generated by `bin/rails g`.
70
70
 
71
71
  ```ruby
@@ -84,6 +84,20 @@ It uses `rubocop -A` to apply `Style/FrozenStringLiteralComment` and other unsaf
84
84
  `rubocop -A` is unsafe autocorrection, but code generated by default is simple and less likely to
85
85
  be incompatible with `rubocop -A`. If you have problems you can replace it with `rubocop -a` instead.
86
86
 
87
+ In Rails 7.2+, it is recommended to use `config.generators.apply_rubocop_autocorrect_after_generate!` instead of the above setting:
88
+
89
+ ```diff
90
+ # config/environments/development.rb
91
+ Rails.application.configure do
92
+ (snip)
93
+ # Apply autocorrection by RuboCop to files generated by `bin/rails generate`.
94
+ - # config.generators.apply_rubocop_autocorrect_after_generate!
95
+ + config.generators.apply_rubocop_autocorrect_after_generate!
96
+ end
97
+ ```
98
+
99
+ You only need to uncomment.
100
+
87
101
  ## The Cops
88
102
 
89
103
  All cops are located under
data/config/default.yml CHANGED
@@ -212,7 +212,9 @@ Rails/ApplicationRecord:
212
212
  Enabled: true
213
213
  SafeAutoCorrect: false
214
214
  VersionAdded: '0.49'
215
- VersionChanged: '2.5'
215
+ VersionChanged: '2.26'
216
+ Exclude:
217
+ - db/**/*.rb
216
218
 
217
219
  Rails/ArelStar:
218
220
  Description: 'Enforces `Arel.star` instead of `"*"` for expanded columns.'
@@ -424,6 +426,14 @@ Rails/EnumHash:
424
426
  Include:
425
427
  - app/models/**/*.rb
426
428
 
429
+ Rails/EnumSyntax:
430
+ Description: 'Use positional arguments over keyword arguments when defining enums.'
431
+ Enabled: pending
432
+ Severity: warning
433
+ VersionAdded: '2.26'
434
+ Include:
435
+ - app/models/**/*.rb
436
+
427
437
  Rails/EnumUniqueness:
428
438
  Description: 'Avoid duplicate integers in hash-syntax `enum` declaration.'
429
439
  Enabled: true
@@ -1185,12 +1195,12 @@ Rails/Validation:
1185
1195
  - app/models/**/*.rb
1186
1196
 
1187
1197
  Rails/WhereEquals:
1188
- Description: 'Pass conditions to `where` as a hash instead of manually constructing SQL.'
1198
+ Description: 'Pass conditions to `where` and `where.not` as a hash instead of manually constructing SQL.'
1189
1199
  StyleGuide: 'https://rails.rubystyle.guide/#hash-conditions'
1190
1200
  Enabled: 'pending'
1191
1201
  SafeAutoCorrect: false
1192
1202
  VersionAdded: '2.9'
1193
- VersionChanged: '2.10'
1203
+ VersionChanged: '2.26'
1194
1204
 
1195
1205
  Rails/WhereExists:
1196
1206
  Description: 'Prefer `exists?(...)` over `where(...).exists?`.'
@@ -1234,6 +1244,10 @@ Rails/WhereRange:
1234
1244
  Style/AndOr:
1235
1245
  EnforcedStyle: conditionals
1236
1246
 
1247
+ Style/CollectionCompact:
1248
+ AllowedReceivers:
1249
+ - params
1250
+
1237
1251
  Style/FormatStringToken:
1238
1252
  AllowedMethods:
1239
1253
  - redirect
@@ -92,11 +92,7 @@ module RuboCop
92
92
  end
93
93
 
94
94
  def range_with_comments(node)
95
- # rubocop:todo InternalAffairs/LocationExpression
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
- # rubocop:todo InternalAffairs/LocationExpression
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
@@ -140,9 +140,9 @@ module RuboCop
140
140
  return unless support_bulk_alter?
141
141
  return unless node.command?(:change_table)
142
142
  return if include_bulk_options?(node)
143
- return unless node.block_node
143
+ return unless (body = node.block_node&.body)
144
144
 
145
- send_nodes = send_nodes_from_change_table_block(node.block_node.body)
145
+ send_nodes = send_nodes_from_change_table_block(body)
146
146
 
147
147
  add_offense_for_change_table(node) if count_transformations(send_nodes) > 1
148
148
  end
@@ -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.reject!(&:blank?) # Same behavior as `ActionController::Parameters#compact_blank!`
35
- # collection.reject! { |_k, v| v.blank? } # Same behavior as `ActionController::Parameters#compact_blank!`
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 reject!].freeze
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 :reject!})
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 :reject!}
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
- if (arguments, receiver_in_block = reject_with_block?(node.parent))
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
- node.method?(:reject) ? 'compact_blank' : 'compact_blank!'
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 'strict'
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 'to_time_in_current_zone' are reported as warning.
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 :enum?, <<~PATTERN
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
- enum?(node) do |pairs|
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: format(MSG, enum: enum_name(key))) do |corrector|
41
- hash = array.children.each_with_index.map do |elem, index|
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
@@ -0,0 +1,128 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # Looks for enums written with keyword arguments syntax.
7
+ #
8
+ # Defining enums with keyword arguments syntax is deprecated and will be removed in Rails 8.0.
9
+ # Positional arguments should be used instead:
10
+ #
11
+ # @example
12
+ # # bad
13
+ # enum status: { active: 0, archived: 1 }, _prefix: true
14
+ #
15
+ # # good
16
+ # enum :status, { active: 0, archived: 1 }, prefix: true
17
+ #
18
+ class EnumSyntax < Base
19
+ extend AutoCorrector
20
+ extend TargetRubyVersion
21
+ extend TargetRailsVersion
22
+
23
+ minimum_target_ruby_version 3.0
24
+ minimum_target_rails_version 7.0
25
+
26
+ MSG = 'Enum defined with keyword arguments in `%<enum>s` enum declaration. Use positional arguments instead.'
27
+ MSG_OPTIONS = 'Enum defined with deprecated options in `%<enum>s` enum declaration. Remove the `_` prefix.'
28
+ RESTRICT_ON_SEND = %i[enum].freeze
29
+
30
+ # From https://github.com/rails/rails/blob/v7.2.1/activerecord/lib/active_record/enum.rb#L231
31
+ OPTION_NAMES = %w[prefix suffix scopes default instance_methods].freeze
32
+ UNDERSCORED_OPTION_NAMES = OPTION_NAMES.map { |option| "_#{option}" }.freeze
33
+
34
+ def_node_matcher :enum?, <<~PATTERN
35
+ (send nil? :enum (hash $...))
36
+ PATTERN
37
+
38
+ def_node_matcher :enum_with_options?, <<~PATTERN
39
+ (send nil? :enum $_ ${array hash} $_)
40
+ PATTERN
41
+
42
+ def on_send(node)
43
+ check_and_correct_keyword_args(node)
44
+ check_enum_options(node)
45
+ end
46
+
47
+ private
48
+
49
+ def check_and_correct_keyword_args(node)
50
+ enum?(node) do |pairs|
51
+ pairs.each do |pair|
52
+ next if option_key?(pair)
53
+
54
+ correct_keyword_args(node, pair.key, pair.value, pairs[1..])
55
+ end
56
+ end
57
+ end
58
+
59
+ def check_enum_options(node)
60
+ enum_with_options?(node) do |key, _, options|
61
+ options.children.each do |option|
62
+ next unless option_key?(option)
63
+
64
+ add_offense(option.key, message: format(MSG_OPTIONS, enum: enum_name_value(key))) do |corrector|
65
+ corrector.replace(option.key, option.key.source.delete_prefix('_'))
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ def correct_keyword_args(node, key, values, options)
72
+ add_offense(values, message: format(MSG, enum: enum_name_value(key))) do |corrector|
73
+ # TODO: Multi-line autocorrect could be implemented in the future.
74
+ next if multiple_enum_definitions?(node)
75
+
76
+ preferred_syntax = "enum #{enum_name(key)}, #{values.source}#{correct_options(options)}"
77
+
78
+ corrector.replace(node, preferred_syntax)
79
+ end
80
+ end
81
+
82
+ def multiple_enum_definitions?(node)
83
+ keys = node.first_argument.keys.map { |key| key.source.delete_prefix('_') }
84
+ filterred_keys = keys.filter { |key| !OPTION_NAMES.include?(key) }
85
+ filterred_keys.size >= 2
86
+ end
87
+
88
+ def enum_name_value(key)
89
+ case key.type
90
+ when :sym, :str
91
+ key.value
92
+ else
93
+ key.source
94
+ end
95
+ end
96
+
97
+ def enum_name(elem)
98
+ case elem.type
99
+ when :str
100
+ elem.value.dump
101
+ when :sym
102
+ elem.value.inspect
103
+ else
104
+ elem.source
105
+ end
106
+ end
107
+
108
+ def option_key?(pair)
109
+ UNDERSCORED_OPTION_NAMES.include?(pair.key.source)
110
+ end
111
+
112
+ def correct_options(options)
113
+ corrected_options = options.map do |pair|
114
+ name = if pair.key.source[0] == '_'
115
+ pair.key.source[1..]
116
+ else
117
+ pair.key.source
118
+ end
119
+
120
+ "#{name}: #{pair.value.source}"
121
+ end.join(', ')
122
+
123
+ ", #{corrected_options}" unless corrected_options.empty?
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
@@ -7,6 +7,18 @@ module RuboCop
7
7
  #
8
8
  # @example
9
9
  # # bad
10
+ # enum :status, { active: 0, archived: 0 }
11
+ #
12
+ # # good
13
+ # enum :status, { active: 0, archived: 1 }
14
+ #
15
+ # # bad
16
+ # enum :status, [:active, :archived, :active]
17
+ #
18
+ # # good
19
+ # enum :status, [:active, :archived]
20
+ #
21
+ # # bad
10
22
  # enum status: { active: 0, archived: 0 }
11
23
  #
12
24
  # # good
@@ -24,6 +36,10 @@ module RuboCop
24
36
  RESTRICT_ON_SEND = %i[enum].freeze
25
37
 
26
38
  def_node_matcher :enum?, <<~PATTERN
39
+ (send nil? :enum $_ ${array hash} ...)
40
+ PATTERN
41
+
42
+ def_node_matcher :enum_with_old_syntax?, <<~PATTERN
27
43
  (send nil? :enum (hash $...))
28
44
  PATTERN
29
45
 
@@ -32,15 +48,17 @@ module RuboCop
32
48
  PATTERN
33
49
 
34
50
  def on_send(node)
35
- enum?(node) do |pairs|
51
+ enum?(node) do |key, args|
52
+ consecutive_duplicates(args.values).each do |item|
53
+ add_offense(item, message: message(key, item))
54
+ end
55
+ end
56
+
57
+ enum_with_old_syntax?(node) do |pairs|
36
58
  pairs.each do |pair|
37
59
  enum_values(pair) do |key, args|
38
- items = args.values
39
-
40
- next unless duplicates?(items)
41
-
42
- consecutive_duplicates(items).each do |item|
43
- add_offense(item, message: format(MSG, value: item.source, enum: enum_name(key)))
60
+ consecutive_duplicates(args.values).each do |item|
61
+ add_offense(item, message: message(key, item))
44
62
  end
45
63
  end
46
64
  end
@@ -57,6 +75,10 @@ module RuboCop
57
75
  key.source
58
76
  end
59
77
  end
78
+
79
+ def message(key, item)
80
+ format(MSG, value: item.source, enum: enum_name(key))
81
+ end
60
82
  end
61
83
  end
62
84
  end
@@ -97,7 +97,7 @@ module RuboCop
97
97
  return unless node.arguments.any? { |e| rails_root_nodes?(e) }
98
98
 
99
99
  register_offense(node, require_to_s: true) do |corrector|
100
- autocorrect_file_join(corrector, node)
100
+ autocorrect_file_join(corrector, node) unless node.first_argument.array_type?
101
101
  end
102
102
  end
103
103
 
@@ -52,7 +52,7 @@ module RuboCop
52
52
  (send
53
53
  nil?
54
54
  {#{FILTERS.join(' ')}}
55
- _
55
+ ...
56
56
  $_)
57
57
  PATTERN
58
58
 
@@ -7,17 +7,26 @@ module RuboCop
7
7
  # and can be replaced with `select`.
8
8
  #
9
9
  # Since `pluck` is an eager method and hits the database immediately,
10
- # using `select` helps to avoid additional database queries.
10
+ # using `select` helps to avoid additional database queries by running as
11
+ # a subquery.
11
12
  #
12
- # This cop has two different enforcement modes. When the `EnforcedStyle`
13
- # is `conservative` (the default) then only calls to `pluck` on a constant
14
- # (i.e. a model class) in the `where` is used as offenses.
13
+ # This cop has two modes of enforcement. When the `EnforcedStyle` is set
14
+ # to `conservative` (the default), only calls to `pluck` on a constant
15
+ # (e.g. a model class) within `where` are considered offenses.
15
16
  #
16
17
  # @safety
17
- # When the `EnforcedStyle` is `aggressive` then all calls to `pluck` in the
18
- # `where` is used as offenses. This may lead to false positives
19
- # as the cop cannot replace to `select` between calls to `pluck` on an
20
- # `ActiveRecord::Relation` instance vs a call to `pluck` on an `Array` instance.
18
+ # When `EnforcedStyle` is set to `aggressive`, all calls to `pluck`
19
+ # within `where` are considered offenses. This might lead to false
20
+ # positives because the check cannot distinguish between calls to
21
+ # `pluck` on an `ActiveRecord::Relation` instance and calls to `pluck`
22
+ # on an `Array` instance.
23
+ #
24
+ # Additionally, when using a subquery with the SQL `IN` operator,
25
+ # databases like PostgreSQL and MySQL can't optimize complex queries as
26
+ # well. They need to scan all records of the outer table against the
27
+ # subquery result sequentially, rather than using an index. This can
28
+ # cause significant performance issues compared to writing the query
29
+ # differently or using `pluck`.
21
30
  #
22
31
  # @example
23
32
  # # bad
@@ -10,25 +10,39 @@ module RuboCop
10
10
  # # bad
11
11
  # 3.day.ago
12
12
  # 1.months.ago
13
+ # 5.megabyte
14
+ # 1.gigabytes
13
15
  #
14
16
  # # good
15
17
  # 3.days.ago
16
18
  # 1.month.ago
19
+ # 5.megabytes
20
+ # 1.gigabyte
17
21
  class PluralizationGrammar < Base
18
22
  extend AutoCorrector
19
23
 
20
- SINGULAR_DURATION_METHODS = { second: :seconds,
21
- minute: :minutes,
22
- hour: :hours,
23
- day: :days,
24
- week: :weeks,
25
- fortnight: :fortnights,
26
- month: :months,
27
- year: :years }.freeze
28
-
29
- RESTRICT_ON_SEND = SINGULAR_DURATION_METHODS.keys + SINGULAR_DURATION_METHODS.values
30
-
31
- PLURAL_DURATION_METHODS = SINGULAR_DURATION_METHODS.invert.freeze
24
+ SINGULAR_METHODS = {
25
+ second: :seconds,
26
+ minute: :minutes,
27
+ hour: :hours,
28
+ day: :days,
29
+ week: :weeks,
30
+ fortnight: :fortnights,
31
+ month: :months,
32
+ year: :years,
33
+ byte: :bytes,
34
+ kilobyte: :kilobytes,
35
+ megabyte: :megabytes,
36
+ gigabyte: :gigabytes,
37
+ terabyte: :terabytes,
38
+ petabyte: :petabytes,
39
+ exabyte: :exabytes,
40
+ zettabyte: :zettabytes
41
+ }.freeze
42
+
43
+ RESTRICT_ON_SEND = SINGULAR_METHODS.keys + SINGULAR_METHODS.values
44
+
45
+ PLURAL_METHODS = SINGULAR_METHODS.invert.freeze
32
46
 
33
47
  MSG = 'Prefer `%<number>s.%<correct>s`.'
34
48
 
@@ -86,15 +100,15 @@ module RuboCop
86
100
  end
87
101
 
88
102
  def pluralize(method_name)
89
- SINGULAR_DURATION_METHODS.fetch(method_name.to_sym).to_s
103
+ SINGULAR_METHODS.fetch(method_name.to_sym).to_s
90
104
  end
91
105
 
92
106
  def singularize(method_name)
93
- PLURAL_DURATION_METHODS.fetch(method_name.to_sym).to_s
107
+ PLURAL_METHODS.fetch(method_name.to_sym).to_s
94
108
  end
95
109
 
96
110
  def duration_method?(method_name)
97
- SINGULAR_DURATION_METHODS.key?(method_name) || PLURAL_DURATION_METHODS.key?(method_name)
111
+ SINGULAR_METHODS.key?(method_name) || PLURAL_METHODS.key?(method_name)
98
112
  end
99
113
  end
100
114
  end
@@ -98,8 +98,6 @@ module RuboCop
98
98
  end
99
99
 
100
100
  def on_or(node)
101
- return unless cop_config['NilOrEmpty']
102
-
103
101
  exists_and_not_empty?(node) do |var1, var2|
104
102
  return unless var1 == var2
105
103
 
@@ -3,35 +3,6 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # TODO: In the future, please support only RuboCop 1.52+ and use `RuboCop::Cop::AllowedReceivers`:
7
- # https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/cop/mixin/allowed_receivers.rb
8
- # At that time, this duplicated module implementation can be removed.
9
- module AllowedReceivers
10
- def allowed_receiver?(receiver)
11
- receiver_name = receiver_name(receiver)
12
-
13
- allowed_receivers.include?(receiver_name)
14
- end
15
-
16
- def receiver_name(receiver)
17
- return receiver_name(receiver.receiver) if receiver.receiver && !receiver.receiver.const_type?
18
-
19
- if receiver.send_type?
20
- if receiver.receiver
21
- "#{receiver_name(receiver.receiver)}.#{receiver.method_name}"
22
- else
23
- receiver.method_name.to_s
24
- end
25
- else
26
- receiver.source
27
- end
28
- end
29
-
30
- def allowed_receivers
31
- cop_config.fetch('AllowedReceivers', [])
32
- end
33
- end
34
-
35
6
  # Detect redundant `all` used as a receiver for Active Record query methods.
36
7
  #
37
8
  # For the methods `delete_all` and `destroy_all`, this cop will only check cases where the receiver is a model.
@@ -40,7 +40,7 @@ module RuboCop
40
40
  def on_send(node)
41
41
  association_with_foreign_key(node) do |type, name, options, foreign_key_pair, foreign_key|
42
42
  if redundant?(node, type, name, options, foreign_key)
43
- add_offense(foreign_key_pair.source_range) do |corrector|
43
+ add_offense(foreign_key_pair) do |corrector|
44
44
  range = range_with_surrounding_space(foreign_key_pair.source_range, side: :left)
45
45
  range = range_with_surrounding_comma(range, :left)
46
46
 
@@ -39,6 +39,9 @@ module RuboCop
39
39
  MSG = 'Remove explicit presence validation for %<association>s.'
40
40
  RESTRICT_ON_SEND = %i[validates].freeze
41
41
 
42
+ # From https://github.com/rails/rails/blob/7a0bf93b9dd291c7f61121a41b3a813ac8857e6a/activemodel/lib/active_model/validations/validates.rb#L157-L159
43
+ NON_VALIDATION_OPTIONS = %i[if unless on allow_blank allow_nil strict].freeze
44
+
42
45
  minimum_target_rails_version 5.0
43
46
 
44
47
  # @!method presence_validation?(node)
@@ -170,6 +173,12 @@ module RuboCop
170
173
 
171
174
  def on_send(node)
172
175
  presence_validation?(node) do |all_keys, options, presence|
176
+ # If presence is the only validation option and other non-validation options
177
+ # are present, removing it will cause rails to error.
178
+ used_option_keys = options.keys.select(&:sym_type?).map(&:value)
179
+ remaining_validations = used_option_keys - NON_VALIDATION_OPTIONS - [:presence]
180
+ return if remaining_validations.none? && options.keys.length > 1
181
+
173
182
  keys = non_optional_belongs_to(node.parent, all_keys)
174
183
  return if keys.none?
175
184
 
@@ -78,7 +78,7 @@ module RuboCop
78
78
 
79
79
  send_nodes.each do |send_node|
80
80
  receiver = send_node.receiver
81
- add_offense(receiver.source_range) do |corrector|
81
+ add_offense(receiver) do |corrector|
82
82
  autocorrect(corrector, send_node, node)
83
83
  end
84
84
  end
@@ -43,7 +43,7 @@ module RuboCop
43
43
  return if reflection_class_name.value.send_type? && reflection_class_name.value.receiver.nil?
44
44
  return if reflection_class_name.value.lvar_type? && str_assigned?(reflection_class_name)
45
45
 
46
- add_offense(reflection_class_name.source_range) do |corrector|
46
+ add_offense(reflection_class_name) do |corrector|
47
47
  autocorrect(corrector, reflection_class_name)
48
48
  end
49
49
  end
@@ -53,9 +53,12 @@ module RuboCop
53
53
  node.pairs.find { |p| p.key.value.to_sym == :content_type }
54
54
  end
55
55
 
56
- def compatible_content_type?(node)
57
- (node && node.value.value == 'text/plain') ||
58
- (!node && !cop_config['ContentTypeCompatibility'])
56
+ def compatible_content_type?(pair_node)
57
+ if pair_node.nil?
58
+ !cop_config['ContentTypeCompatibility']
59
+ elsif pair_node.value.respond_to?(:value)
60
+ pair_node.value.value == 'text/plain'
61
+ end
59
62
  end
60
63
 
61
64
  def replacement(rest_options, option_value)
@@ -34,7 +34,7 @@ module RuboCop
34
34
  referer?(node) do
35
35
  return unless node.method?(wrong_method_name)
36
36
 
37
- add_offense(node.source_range) do |corrector|
37
+ add_offense(node) do |corrector|
38
38
  corrector.replace(node, "request.#{style}")
39
39
  end
40
40
  end
@@ -23,6 +23,8 @@ module RuboCop
23
23
  # File.binread(Rails.root.join('db', 'schema.rb'))
24
24
  # File.write(Rails.root.join('db', 'schema.rb'), content)
25
25
  # File.binwrite(Rails.root.join('db', 'schema.rb'), content)
26
+ # Dir.glob(Rails.root.join('db', 'schema.rb'))
27
+ # Dir[Rails.root.join('db', 'schema.rb')]
26
28
  #
27
29
  # # good
28
30
  # Rails.root.join('db', 'schema.rb').open
@@ -31,14 +33,15 @@ module RuboCop
31
33
  # Rails.root.join('db', 'schema.rb').binread
32
34
  # Rails.root.join('db', 'schema.rb').write(content)
33
35
  # Rails.root.join('db', 'schema.rb').binwrite(content)
36
+ # Rails.root.glob("db/schema.rb")
34
37
  #
35
38
  class RootPathnameMethods < Base # rubocop:disable Metrics/ClassLength
36
39
  extend AutoCorrector
37
40
  include RangeHelp
38
41
 
39
- MSG = '`%<rails_root>s` is a `Pathname` so you can just append `#%<method>s`.'
42
+ MSG = '`%<rails_root>s` is a `Pathname`, so you can use `%<replacement>s`.'
40
43
 
41
- DIR_GLOB_METHODS = %i[glob].to_set.freeze
44
+ DIR_GLOB_METHODS = %i[[] glob].to_set.freeze
42
45
 
43
46
  DIR_NON_GLOB_METHODS = %i[
44
47
  children
@@ -171,7 +174,7 @@ module RuboCop
171
174
 
172
175
  def_node_matcher :dir_glob?, <<~PATTERN
173
176
  (send
174
- (const {cbase nil?} :Dir) :glob ...)
177
+ (const {cbase nil?} :Dir) DIR_GLOB_METHODS ...)
175
178
  PATTERN
176
179
 
177
180
  def_node_matcher :rails_root_pathname?, <<~PATTERN
@@ -188,13 +191,14 @@ module RuboCop
188
191
 
189
192
  def on_send(node)
190
193
  evidence(node) do |method, path, args, rails_root|
191
- add_offense(node, message: format(MSG, method: method, rails_root: rails_root.source)) do |corrector|
192
- replacement = if dir_glob?(node)
193
- build_path_glob_replacement(path, method)
194
- else
195
- build_path_replacement(path, method, args)
196
- end
194
+ replacement = if dir_glob?(node)
195
+ build_path_glob_replacement(path)
196
+ else
197
+ build_path_replacement(path, method, args)
198
+ end
197
199
 
200
+ message = format(MSG, rails_root: rails_root.source, replacement: replacement)
201
+ add_offense(node, message: message) do |corrector|
198
202
  corrector.replace(node, replacement)
199
203
  end
200
204
  end
@@ -217,12 +221,12 @@ module RuboCop
217
221
  end
218
222
  end
219
223
 
220
- def build_path_glob_replacement(path, method)
224
+ def build_path_glob_replacement(path)
221
225
  receiver = range_between(path.source_range.begin_pos, path.children.first.loc.selector.end_pos).source
222
226
 
223
227
  argument = path.arguments.one? ? path.first_argument.source : join_arguments(path.arguments)
224
228
 
225
- "#{receiver}.#{method}(#{argument})"
229
+ "#{receiver}.glob(#{argument})"
226
230
  end
227
231
 
228
232
  def build_path_replacement(path, method, args)
@@ -100,7 +100,8 @@ module RuboCop
100
100
  end
101
101
 
102
102
  def forbidden_methods
103
- obsolete_result = cop_config['Blacklist']
103
+ # TODO: Remove when RuboCop Rails 3 releases.
104
+ obsolete_result = cop_config['Blacklist'] # rubocop:disable InternalAffairs/UndefinedConfig
104
105
  if obsolete_result
105
106
  warn '`Blacklist` has been renamed to `ForbiddenMethods`.' unless @displayed_forbidden_warning
106
107
  @displayed_forbidden_warning = true
@@ -111,7 +112,8 @@ module RuboCop
111
112
  end
112
113
 
113
114
  def allowed_methods
114
- obsolete_result = cop_config['Whitelist']
115
+ # TODO: Remove when RuboCop Rails 3 releases.
116
+ obsolete_result = cop_config['Whitelist'] # rubocop:disable InternalAffairs/UndefinedConfig
115
117
  if obsolete_result
116
118
  warn '`Whitelist` has been renamed to `AllowedMethods`.' unless @displayed_allowed_warning
117
119
  @displayed_allowed_warning = true
@@ -59,11 +59,11 @@ module RuboCop
59
59
 
60
60
  def on_send(node)
61
61
  return if node.receiver
62
+ return unless (last_argument = node.last_argument)
62
63
 
63
64
  range = node.loc.selector
64
65
 
65
66
  add_offense(range, message: message(node)) do |corrector|
66
- last_argument = node.last_argument
67
67
  return if !last_argument.literal? && !last_argument.splat_type? && !frozen_array_argument?(last_argument)
68
68
 
69
69
  corrector.replace(range, 'validates')
@@ -4,7 +4,8 @@ module RuboCop
4
4
  module Cop
5
5
  module Rails
6
6
  # Identifies places where manually constructed SQL
7
- # in `where` can be replaced with `where(attribute: value)`.
7
+ # in `where` and `where.not` can be replaced with
8
+ # `where(attribute: value)` and `where.not(attribute: value)`.
8
9
  #
9
10
  # @safety
10
11
  # This cop's autocorrection is unsafe because is may change SQL.
@@ -13,6 +14,7 @@ module RuboCop
13
14
  # @example
14
15
  # # bad
15
16
  # User.where('name = ?', 'Gabe')
17
+ # User.where.not('name = ?', 'Gabe')
16
18
  # User.where('name = :name', name: 'Gabe')
17
19
  # User.where('name IS NULL')
18
20
  # User.where('name IN (?)', ['john', 'jane'])
@@ -21,6 +23,7 @@ module RuboCop
21
23
  #
22
24
  # # good
23
25
  # User.where(name: 'Gabe')
26
+ # User.where.not(name: 'Gabe')
24
27
  # User.where(name: nil)
25
28
  # User.where(name: ['john', 'jane'])
26
29
  # User.where(users: { name: 'Gabe' })
@@ -29,25 +32,27 @@ module RuboCop
29
32
  extend AutoCorrector
30
33
 
31
34
  MSG = 'Use `%<good_method>s` instead of manually constructing SQL.'
32
- RESTRICT_ON_SEND = %i[where].freeze
35
+ RESTRICT_ON_SEND = %i[where not].freeze
33
36
 
34
37
  def_node_matcher :where_method_call?, <<~PATTERN
35
38
  {
36
- (call _ :where (array $str_type? $_ ?))
37
- (call _ :where $str_type? $_ ?)
39
+ (call _ {:where :not} (array $str_type? $_ ?))
40
+ (call _ {:where :not} $str_type? $_ ?)
38
41
  }
39
42
  PATTERN
40
43
 
41
44
  def on_send(node)
45
+ return if node.method?(:not) && !where_not?(node)
46
+
42
47
  where_method_call?(node) do |template_node, value_node|
43
48
  value_node = value_node.first
44
49
 
45
50
  range = offense_range(node)
46
51
 
47
- column_and_value = extract_column_and_value(template_node, value_node)
48
- return unless column_and_value
52
+ column, value = extract_column_and_value(template_node, value_node)
53
+ return unless value
49
54
 
50
- good_method = build_good_method(*column_and_value)
55
+ good_method = build_good_method(node.method_name, column, value)
51
56
  message = format(MSG, good_method: good_method)
52
57
 
53
58
  add_offense(range, message: message) do |corrector|
@@ -69,11 +74,12 @@ module RuboCop
69
74
  range_between(node.loc.selector.begin_pos, node.source_range.end_pos)
70
75
  end
71
76
 
77
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
72
78
  def extract_column_and_value(template_node, value_node)
73
79
  value =
74
80
  case template_node.value
75
81
  when EQ_ANONYMOUS_RE, IN_ANONYMOUS_RE
76
- value_node.source
82
+ value_node&.source
77
83
  when EQ_NAMED_RE, IN_NAMED_RE
78
84
  return unless value_node&.hash_type?
79
85
 
@@ -85,18 +91,28 @@ module RuboCop
85
91
  return
86
92
  end
87
93
 
88
- [Regexp.last_match(1), value]
94
+ column_qualifier = Regexp.last_match(1)
95
+ return if column_qualifier.count('.') > 1
96
+
97
+ [column_qualifier, value]
89
98
  end
99
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
90
100
 
91
- def build_good_method(column, value)
101
+ def build_good_method(method_name, column, value)
92
102
  if column.include?('.')
93
103
  table, column = column.split('.')
94
104
 
95
- "where(#{table}: { #{column}: #{value} })"
105
+ "#{method_name}(#{table}: { #{column}: #{value} })"
96
106
  else
97
- "where(#{column}: #{value})"
107
+ "#{method_name}(#{column}: #{value})"
98
108
  end
99
109
  end
110
+
111
+ def where_not?(node)
112
+ return false unless (receiver = node.receiver)
113
+
114
+ receiver.send_type? && receiver.method?(:where)
115
+ end
100
116
  end
101
117
  end
102
118
  end
@@ -43,10 +43,10 @@ module RuboCop
43
43
 
44
44
  range = offense_range(node)
45
45
 
46
- column_and_value = extract_column_and_value(template_node, value_node)
47
- return unless column_and_value
46
+ column, value = extract_column_and_value(template_node, value_node)
47
+ return unless value
48
48
 
49
- good_method = build_good_method(node.loc.dot&.source, *column_and_value)
49
+ good_method = build_good_method(node.loc.dot&.source, column, value)
50
50
  message = format(MSG, good_method: good_method)
51
51
 
52
52
  add_offense(range, message: message) do |corrector|
@@ -68,13 +68,14 @@ module RuboCop
68
68
  range_between(node.loc.selector.begin_pos, node.source_range.end_pos)
69
69
  end
70
70
 
71
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
71
72
  def extract_column_and_value(template_node, value_node)
72
73
  value =
73
74
  case template_node.value
74
75
  when NOT_EQ_ANONYMOUS_RE, NOT_IN_ANONYMOUS_RE
75
- value_node.source
76
+ value_node&.source
76
77
  when NOT_EQ_NAMED_RE, NOT_IN_NAMED_RE
77
- return unless value_node.hash_type?
78
+ return unless value_node&.hash_type?
78
79
 
79
80
  pair = value_node.pairs.find { |p| p.key.value.to_sym == Regexp.last_match(2).to_sym }
80
81
  pair.value.source
@@ -84,8 +85,12 @@ module RuboCop
84
85
  return
85
86
  end
86
87
 
87
- [Regexp.last_match(1), value]
88
+ column_qualifier = Regexp.last_match(1)
89
+ return if column_qualifier.count('.') > 1
90
+
91
+ [column_qualifier, value]
88
92
  end
93
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
89
94
 
90
95
  def build_good_method(dot, column, value)
91
96
  dot ||= '.'
@@ -140,6 +140,8 @@ module RuboCop
140
140
  rhs = pair2.value
141
141
  end
142
142
  end
143
+ else
144
+ return
143
145
  end
144
146
 
145
147
  if lhs
@@ -150,7 +152,10 @@ module RuboCop
150
152
  rhs_source = parentheses_needed?(rhs) ? "(#{rhs.source})" : rhs.source
151
153
  end
152
154
 
153
- [Regexp.last_match(1), "#{lhs_source}#{operator}#{rhs_source}"] if operator
155
+ column_qualifier = Regexp.last_match(1)
156
+ return if column_qualifier.count('.') > 1
157
+
158
+ [column_qualifier, "#{lhs_source}#{operator}#{rhs_source}"] if operator
154
159
  end
155
160
  # rubocop:enable Metrics
156
161
 
@@ -46,6 +46,7 @@ require_relative 'rails/duration_arithmetic'
46
46
  require_relative 'rails/dynamic_find_by'
47
47
  require_relative 'rails/eager_evaluation_log_message'
48
48
  require_relative 'rails/enum_hash'
49
+ require_relative 'rails/enum_syntax'
49
50
  require_relative 'rails/enum_uniqueness'
50
51
  require_relative 'rails/env_local'
51
52
  require_relative 'rails/environment_comparison'
@@ -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.25.1'
7
+ STRING = '2.26.2'
8
8
 
9
9
  def self.document_version
10
10
  STRING.match('\d+\.\d+').to_s
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.25.1
4
+ version: 2.26.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2024-06-29 00:00:00.000000000 Z
13
+ date: 2024-09-21 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -46,7 +46,7 @@ dependencies:
46
46
  requirements:
47
47
  - - ">="
48
48
  - !ruby/object:Gem::Version
49
- version: 1.33.0
49
+ version: 1.52.0
50
50
  - - "<"
51
51
  - !ruby/object:Gem::Version
52
52
  version: '2.0'
@@ -56,7 +56,7 @@ dependencies:
56
56
  requirements:
57
57
  - - ">="
58
58
  - !ruby/object:Gem::Version
59
- version: 1.33.0
59
+ version: 1.52.0
60
60
  - - "<"
61
61
  - !ruby/object:Gem::Version
62
62
  version: '2.0'
@@ -140,6 +140,7 @@ files:
140
140
  - lib/rubocop/cop/rails/dynamic_find_by.rb
141
141
  - lib/rubocop/cop/rails/eager_evaluation_log_message.rb
142
142
  - lib/rubocop/cop/rails/enum_hash.rb
143
+ - lib/rubocop/cop/rails/enum_syntax.rb
143
144
  - lib/rubocop/cop/rails/enum_uniqueness.rb
144
145
  - lib/rubocop/cop/rails/env_local.rb
145
146
  - lib/rubocop/cop/rails/environment_comparison.rb
@@ -246,7 +247,7 @@ metadata:
246
247
  homepage_uri: https://docs.rubocop.org/rubocop-rails/
247
248
  changelog_uri: https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md
248
249
  source_code_uri: https://github.com/rubocop/rubocop-rails/
249
- documentation_uri: https://docs.rubocop.org/rubocop-rails/2.25/
250
+ documentation_uri: https://docs.rubocop.org/rubocop-rails/2.26/
250
251
  bug_tracker_uri: https://github.com/rubocop/rubocop-rails/issues
251
252
  rubygems_mfa_required: 'true'
252
253
  post_install_message:
@@ -264,7 +265,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
264
265
  - !ruby/object:Gem::Version
265
266
  version: '0'
266
267
  requirements: []
267
- rubygems_version: 3.5.11
268
+ rubygems_version: 3.5.16
268
269
  signing_key:
269
270
  specification_version: 4
270
271
  summary: Automatic Rails code style checking tool.