rubocop-rails 2.32.0 → 2.34.3

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/config/default.yml +47 -3
  4. data/lib/rubocop/cop/mixin/active_record_helper.rb +1 -1
  5. data/lib/rubocop/cop/mixin/index_method.rb +4 -0
  6. data/lib/rubocop/cop/rails/action_controller_flash_before_render.rb +4 -2
  7. data/lib/rubocop/cop/rails/delegate.rb +4 -4
  8. data/lib/rubocop/cop/rails/duplicate_association.rb +1 -1
  9. data/lib/rubocop/cop/rails/duplicate_scope.rb +2 -2
  10. data/lib/rubocop/cop/rails/env.rb +57 -0
  11. data/lib/rubocop/cop/rails/env_local.rb +50 -26
  12. data/lib/rubocop/cop/rails/environment_comparison.rb +56 -48
  13. data/lib/rubocop/cop/rails/exit.rb +7 -4
  14. data/lib/rubocop/cop/rails/file_path.rb +2 -2
  15. data/lib/rubocop/cop/rails/find_by.rb +1 -1
  16. data/lib/rubocop/cop/rails/find_by_or_assignment_memoization.rb +124 -0
  17. data/lib/rubocop/cop/rails/helper_instance_variable.rb +16 -17
  18. data/lib/rubocop/cop/rails/http_status_name_consistency.rb +80 -0
  19. data/lib/rubocop/cop/rails/index_with.rb +5 -0
  20. data/lib/rubocop/cop/rails/inverse_of.rb +7 -0
  21. data/lib/rubocop/cop/rails/order_arguments.rb +84 -0
  22. data/lib/rubocop/cop/rails/output.rb +3 -0
  23. data/lib/rubocop/cop/rails/output_safety.rb +3 -1
  24. data/lib/rubocop/cop/rails/pluck.rb +6 -3
  25. data/lib/rubocop/cop/rails/presence.rb +67 -18
  26. data/lib/rubocop/cop/rails/read_write_attribute.rb +1 -1
  27. data/lib/rubocop/cop/rails/redirect_back_or_to.rb +99 -0
  28. data/lib/rubocop/cop/rails/redundant_presence_validation_on_belongs_to.rb +3 -3
  29. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +1 -1
  30. data/lib/rubocop/cop/rails/save_bang.rb +2 -2
  31. data/lib/rubocop/cop/rails/select_map.rb +12 -4
  32. data/lib/rubocop/cop/rails/transaction_exit_statement.rb +4 -1
  33. data/lib/rubocop/cop/rails/where_exists.rb +5 -5
  34. data/lib/rubocop/cop/rails_cops.rb +5 -0
  35. data/lib/rubocop/rails/version.rb +1 -1
  36. metadata +9 -4
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # Checks for uses of `redirect_back(fallback_location: ...)` and
7
+ # suggests using `redirect_back_or_to(...)` instead.
8
+ #
9
+ # `redirect_back(fallback_location: ...)` was soft deprecated in Rails 7.0 and
10
+ # `redirect_back_or_to` was introduced as a replacement.
11
+ #
12
+ # @example
13
+ # # bad
14
+ # redirect_back(fallback_location: root_path)
15
+ #
16
+ # # good
17
+ # redirect_back_or_to(root_path)
18
+ #
19
+ # # bad
20
+ # redirect_back(fallback_location: root_path, allow_other_host: false)
21
+ #
22
+ # # good
23
+ # redirect_back_or_to(root_path, allow_other_host: false)
24
+ #
25
+ class RedirectBackOrTo < Base
26
+ extend AutoCorrector
27
+ extend TargetRailsVersion
28
+
29
+ minimum_target_rails_version 7.0
30
+
31
+ MSG = 'Use `redirect_back_or_to` instead of `redirect_back` with `:fallback_location` keyword argument.'
32
+ RESTRICT_ON_SEND = %i[redirect_back].freeze
33
+
34
+ def_node_matcher :redirect_back_with_fallback_location, <<~PATTERN
35
+ (send nil? :redirect_back
36
+ (hash <$(pair (sym :fallback_location) $_) $...>)
37
+ )
38
+ PATTERN
39
+
40
+ def on_send(node)
41
+ redirect_back_with_fallback_location(node) do |fallback_pair, fallback_value, options|
42
+ add_offense(node.loc.selector) do |corrector|
43
+ correct_redirect_back(corrector, node, fallback_pair, fallback_value, options)
44
+ end
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ # rubocop:disable Metrics/AbcSize
51
+ def correct_redirect_back(corrector, node, fallback_pair, fallback_value, options)
52
+ corrector.replace(node.loc.selector, 'redirect_back_or_to')
53
+
54
+ hash_arg = node.first_argument
55
+
56
+ if hash_arg.pairs.one?
57
+ arguments = [fallback_value.source] + options.map(&:source)
58
+ corrector.replace(hash_arg, arguments.join(', '))
59
+ else
60
+ remove_fallback_location_pair(corrector, hash_arg, fallback_pair)
61
+ first_pair = hash_arg.pairs.find { |pair| pair != fallback_pair }
62
+ corrector.insert_before(first_pair, "#{fallback_value.source}, ")
63
+ end
64
+
65
+ wrap_with_parentheses(node, corrector) unless node.parenthesized?
66
+ end
67
+ # rubocop:enable Metrics/AbcSize
68
+
69
+ def remove_fallback_location_pair(corrector, hash_node, fallback_pair)
70
+ pairs = hash_node.pairs
71
+ index = pairs.index(fallback_pair)
72
+
73
+ if pairs.one?
74
+ corrector.remove(fallback_pair)
75
+ elsif index.zero?
76
+ remove_first_pair(corrector, fallback_pair, pairs[1])
77
+ else
78
+ remove_non_first_pair(corrector, fallback_pair, pairs[index - 1])
79
+ end
80
+ end
81
+
82
+ def wrap_with_parentheses(node, corrector)
83
+ corrector.replace(node.loc.selector.end.join(node.first_argument.source_range.begin), '(')
84
+ corrector.insert_after(node, ')')
85
+ end
86
+
87
+ def remove_first_pair(corrector, fallback_pair, next_pair)
88
+ range = fallback_pair.source_range.join(next_pair.source_range.begin)
89
+ corrector.remove(range)
90
+ end
91
+
92
+ def remove_non_first_pair(corrector, fallback_pair, prev_pair)
93
+ range = prev_pair.source_range.end.join(fallback_pair.source_range.end)
94
+ corrector.remove(range)
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -74,7 +74,7 @@ module RuboCop
74
74
  $[
75
75
  (hash <$(pair (sym :presence) true) ...>) # presence: true
76
76
  !(hash <$(pair (sym :strict) {true const}) ...>) # strict: true
77
- !(hash <$(pair (sym {:if :unless}) _) ...>) # if: some_condition or unless: some_condition
77
+ !(hash <$(pair (sym {:if}) _) ...>) # if: some_condition or unless: some_condition
78
78
  ]
79
79
  )
80
80
  PATTERN
@@ -211,12 +211,12 @@ module RuboCop
211
211
 
212
212
  def non_optional_belongs_to(node, keys)
213
213
  keys.select do |key|
214
- belongs_to = belongs_to_for(node, key)
214
+ belongs_to = belongs_to_for?(node, key)
215
215
  belongs_to && !optional?(belongs_to)
216
216
  end
217
217
  end
218
218
 
219
- def belongs_to_for(model_class_node, key)
219
+ def belongs_to_for?(model_class_node, key)
220
220
  if key.to_s.end_with?('_id')
221
221
  normalized_key = key.to_s.delete_suffix('_id').to_sym
222
222
  belongs_to?(model_class_node, key: normalized_key, fk: key)
@@ -71,7 +71,7 @@ module RuboCop
71
71
  def on_block(node)
72
72
  return unless node.method?(:with_options)
73
73
  return unless (body = node.body)
74
- return unless all_block_nodes_in(body).count.zero?
74
+ return unless all_block_nodes_in(body).none?
75
75
 
76
76
  send_nodes = all_send_nodes_in(body)
77
77
  return unless redundant_receiver?(send_nodes, node)
@@ -156,7 +156,7 @@ module RuboCop
156
156
  return unless persist_method?(node)
157
157
  return if return_value_assigned?(node)
158
158
  return if implicit_return?(node)
159
- return if check_used_in_condition_or_compound_boolean(node)
159
+ return if check_used_in_condition_or_compound_boolean?(node)
160
160
  return if argument?(node)
161
161
  return if explicit_return?(node)
162
162
  return if checked_immediately?(node)
@@ -227,7 +227,7 @@ module RuboCop
227
227
  array
228
228
  end
229
229
 
230
- def check_used_in_condition_or_compound_boolean(node)
230
+ def check_used_in_condition_or_compound_boolean?(node)
231
231
  return false unless in_condition_or_compound_boolean?(node)
232
232
 
233
233
  register_offense(node, CREATE_CONDITIONAL_MSG) unless MODIFY_PERSIST_METHODS.include?(node.method_name)
@@ -45,18 +45,26 @@ module RuboCop
45
45
  private
46
46
 
47
47
  def find_select_node(node, column_name)
48
- node.descendants.detect do |select_candidate|
48
+ select_method_nodes = node.descendants.select do |select_candidate|
49
49
  next if !select_candidate.call_type? || !select_candidate.method?(:select)
50
50
 
51
51
  match_column_name?(select_candidate, column_name)
52
52
  end
53
+
54
+ return unless select_method_nodes.one?
55
+
56
+ select_method_nodes.first
53
57
  end
54
58
 
55
59
  # rubocop:disable Metrics/AbcSize
56
60
  def autocorrect(corrector, select_node, node, preferred_method)
57
- corrector.remove(select_node.parent.loc.dot)
58
- corrector.remove(select_node.loc.selector.begin.join(select_node.source_range.end))
59
- corrector.replace(node.loc.selector.begin.join(node.source_range.end), preferred_method)
61
+ if (parent = select_node.parent).loc?(:dot)
62
+ corrector.remove(parent.loc.dot)
63
+ corrector.remove(select_node.loc.selector.begin.join(select_node.source_range.end))
64
+ corrector.replace(node.loc.selector.begin.join(node.source_range.end), preferred_method)
65
+ else
66
+ corrector.replace(node, "#{select_node.receiver.source}.#{preferred_method}")
67
+ end
60
68
  end
61
69
  # rubocop:enable Metrics/AbcSize
62
70
 
@@ -98,8 +98,11 @@ module RuboCop
98
98
  def in_transaction_block?(node)
99
99
  return false unless transaction_method_name?(node.method_name)
100
100
  return false unless (parent = node.parent)
101
+ return false unless parent.any_block_type? && parent.body
101
102
 
102
- parent.any_block_type? && parent.body
103
+ node.right_siblings.none? do |sibling|
104
+ sibling.respond_to?(:loop_keyword?) && sibling.loop_keyword?
105
+ end
103
106
  end
104
107
 
105
108
  def statement(statement_node)
@@ -58,12 +58,12 @@ module RuboCop
58
58
  (call (call _ :where $...) :exists?)
59
59
  PATTERN
60
60
 
61
- def_node_matcher :exists_with_args?, <<~PATTERN
62
- (call _ :exists? $...)
61
+ def_node_matcher :exists_with_arg?, <<~PATTERN
62
+ (call _ :exists? $!splat_type?)
63
63
  PATTERN
64
64
 
65
65
  def on_send(node)
66
- find_offenses(node) do |args|
66
+ find_offenses?(node) do |args|
67
67
  return unless convertable_args?(args)
68
68
 
69
69
  range = correction_range(node)
@@ -87,11 +87,11 @@ module RuboCop
87
87
  style == :exists
88
88
  end
89
89
 
90
- def find_offenses(node, &block)
90
+ def find_offenses?(node, &block)
91
91
  if exists_style?
92
92
  where_exists_call?(node, &block)
93
93
  elsif where_style?
94
- exists_with_args?(node, &block)
94
+ exists_with_arg?(node) { |arg| yield([arg]) }
95
95
  end
96
96
  end
97
97
 
@@ -50,6 +50,7 @@ require_relative 'rails/eager_evaluation_log_message'
50
50
  require_relative 'rails/enum_hash'
51
51
  require_relative 'rails/enum_syntax'
52
52
  require_relative 'rails/enum_uniqueness'
53
+ require_relative 'rails/env'
53
54
  require_relative 'rails/env_local'
54
55
  require_relative 'rails/environment_comparison'
55
56
  require_relative 'rails/environment_variable_access'
@@ -58,6 +59,7 @@ require_relative 'rails/expanded_date_range'
58
59
  require_relative 'rails/file_path'
59
60
  require_relative 'rails/find_by'
60
61
  require_relative 'rails/find_by_id'
62
+ require_relative 'rails/find_by_or_assignment_memoization'
61
63
  require_relative 'rails/find_each'
62
64
  require_relative 'rails/freeze_time'
63
65
  require_relative 'rails/has_and_belongs_to_many'
@@ -65,6 +67,7 @@ require_relative 'rails/has_many_or_has_one_dependent'
65
67
  require_relative 'rails/helper_instance_variable'
66
68
  require_relative 'rails/http_positional_arguments'
67
69
  require_relative 'rails/http_status'
70
+ require_relative 'rails/http_status_name_consistency'
68
71
  require_relative 'rails/i18n_lazy_lookup'
69
72
  require_relative 'rails/i18n_locale_assignment'
70
73
  require_relative 'rails/i18n_locale_texts'
@@ -82,6 +85,7 @@ require_relative 'rails/migration_class_name'
82
85
  require_relative 'rails/multiple_route_paths'
83
86
  require_relative 'rails/negate_include'
84
87
  require_relative 'rails/not_null_column'
88
+ require_relative 'rails/order_arguments'
85
89
  require_relative 'rails/order_by_id'
86
90
  require_relative 'rails/output'
87
91
  require_relative 'rails/output_safety'
@@ -100,6 +104,7 @@ require_relative 'rails/redundant_foreign_key'
100
104
  require_relative 'rails/redundant_presence_validation_on_belongs_to'
101
105
  require_relative 'rails/redundant_receiver_in_with_options'
102
106
  require_relative 'rails/redundant_travel_back'
107
+ require_relative 'rails/redirect_back_or_to'
103
108
  require_relative 'rails/reflection_class_name'
104
109
  require_relative 'rails/refute_methods'
105
110
  require_relative 'rails/relative_date_constant'
@@ -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.32.0'
7
+ STRING = '2.34.3'
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.32.0
4
+ version: 2.34.3
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-05-17 00:00:00.000000000 Z
12
+ date: 1980-01-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -156,6 +156,7 @@ files:
156
156
  - lib/rubocop/cop/rails/enum_hash.rb
157
157
  - lib/rubocop/cop/rails/enum_syntax.rb
158
158
  - lib/rubocop/cop/rails/enum_uniqueness.rb
159
+ - lib/rubocop/cop/rails/env.rb
159
160
  - lib/rubocop/cop/rails/env_local.rb
160
161
  - lib/rubocop/cop/rails/environment_comparison.rb
161
162
  - lib/rubocop/cop/rails/environment_variable_access.rb
@@ -164,6 +165,7 @@ files:
164
165
  - lib/rubocop/cop/rails/file_path.rb
165
166
  - lib/rubocop/cop/rails/find_by.rb
166
167
  - lib/rubocop/cop/rails/find_by_id.rb
168
+ - lib/rubocop/cop/rails/find_by_or_assignment_memoization.rb
167
169
  - lib/rubocop/cop/rails/find_each.rb
168
170
  - lib/rubocop/cop/rails/freeze_time.rb
169
171
  - lib/rubocop/cop/rails/has_and_belongs_to_many.rb
@@ -171,6 +173,7 @@ files:
171
173
  - lib/rubocop/cop/rails/helper_instance_variable.rb
172
174
  - lib/rubocop/cop/rails/http_positional_arguments.rb
173
175
  - lib/rubocop/cop/rails/http_status.rb
176
+ - lib/rubocop/cop/rails/http_status_name_consistency.rb
174
177
  - lib/rubocop/cop/rails/i18n_lazy_lookup.rb
175
178
  - lib/rubocop/cop/rails/i18n_locale_assignment.rb
176
179
  - lib/rubocop/cop/rails/i18n_locale_texts.rb
@@ -188,6 +191,7 @@ files:
188
191
  - lib/rubocop/cop/rails/multiple_route_paths.rb
189
192
  - lib/rubocop/cop/rails/negate_include.rb
190
193
  - lib/rubocop/cop/rails/not_null_column.rb
194
+ - lib/rubocop/cop/rails/order_arguments.rb
191
195
  - lib/rubocop/cop/rails/order_by_id.rb
192
196
  - lib/rubocop/cop/rails/output.rb
193
197
  - lib/rubocop/cop/rails/output_safety.rb
@@ -200,6 +204,7 @@ files:
200
204
  - lib/rubocop/cop/rails/present.rb
201
205
  - lib/rubocop/cop/rails/rake_environment.rb
202
206
  - lib/rubocop/cop/rails/read_write_attribute.rb
207
+ - lib/rubocop/cop/rails/redirect_back_or_to.rb
203
208
  - lib/rubocop/cop/rails/redundant_active_record_all_method.rb
204
209
  - lib/rubocop/cop/rails/redundant_allow_nil.rb
205
210
  - lib/rubocop/cop/rails/redundant_foreign_key.rb
@@ -264,7 +269,7 @@ metadata:
264
269
  homepage_uri: https://docs.rubocop.org/rubocop-rails/
265
270
  changelog_uri: https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md
266
271
  source_code_uri: https://github.com/rubocop/rubocop-rails/
267
- documentation_uri: https://docs.rubocop.org/rubocop-rails/2.32/
272
+ documentation_uri: https://docs.rubocop.org/rubocop-rails/2.34/
268
273
  bug_tracker_uri: https://github.com/rubocop/rubocop-rails/issues
269
274
  rubygems_mfa_required: 'true'
270
275
  default_lint_roller_plugin: RuboCop::Rails::Plugin
@@ -282,7 +287,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
282
287
  - !ruby/object:Gem::Version
283
288
  version: '0'
284
289
  requirements: []
285
- rubygems_version: 3.6.2
290
+ rubygems_version: 4.0.3
286
291
  specification_version: 4
287
292
  summary: Automatic Rails code style checking tool.
288
293
  test_files: []