rubocop-rails 2.26.0 → 2.29.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +51 -1
  4. data/config/default.yml +30 -6
  5. data/lib/rubocop/cop/mixin/index_method.rb +12 -5
  6. data/lib/rubocop/cop/mixin/routes_helper.rb +20 -0
  7. data/lib/rubocop/cop/mixin/target_rails_version.rb +3 -5
  8. data/lib/rubocop/cop/rails/action_controller_flash_before_render.rb +5 -5
  9. data/lib/rubocop/cop/rails/action_order.rb +1 -5
  10. data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +1 -5
  11. data/lib/rubocop/cop/rails/add_column_index.rb +1 -0
  12. data/lib/rubocop/cop/rails/application_record.rb +4 -0
  13. data/lib/rubocop/cop/rails/bulk_change_table.rb +1 -0
  14. data/lib/rubocop/cop/rails/compact_blank.rb +8 -4
  15. data/lib/rubocop/cop/rails/dangerous_column_names.rb +2 -0
  16. data/lib/rubocop/cop/rails/duplicate_association.rb +8 -4
  17. data/lib/rubocop/cop/rails/enum_syntax.rb +18 -14
  18. data/lib/rubocop/cop/rails/env_local.rb +26 -3
  19. data/lib/rubocop/cop/rails/file_path.rb +26 -3
  20. data/lib/rubocop/cop/rails/http_positional_arguments.rb +7 -0
  21. data/lib/rubocop/cop/rails/index_by.rb +28 -12
  22. data/lib/rubocop/cop/rails/index_with.rb +28 -12
  23. data/lib/rubocop/cop/rails/match_route.rb +1 -9
  24. data/lib/rubocop/cop/rails/multiple_route_paths.rb +50 -0
  25. data/lib/rubocop/cop/rails/not_null_column.rb +6 -2
  26. data/lib/rubocop/cop/rails/pluck.rb +20 -0
  27. data/lib/rubocop/cop/rails/pluralization_grammar.rb +1 -1
  28. data/lib/rubocop/cop/rails/present.rb +0 -2
  29. data/lib/rubocop/cop/rails/redundant_active_record_all_method.rb +1 -30
  30. data/lib/rubocop/cop/rails/redundant_foreign_key.rb +1 -1
  31. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +1 -1
  32. data/lib/rubocop/cop/rails/reflection_class_name.rb +1 -1
  33. data/lib/rubocop/cop/rails/request_referer.rb +1 -1
  34. data/lib/rubocop/cop/rails/reversible_migration.rb +3 -1
  35. data/lib/rubocop/cop/rails/root_pathname_methods.rb +17 -8
  36. data/lib/rubocop/cop/rails/save_bang.rb +4 -3
  37. data/lib/rubocop/cop/rails/schema_comment.rb +1 -0
  38. data/lib/rubocop/cop/rails/select_map.rb +3 -2
  39. data/lib/rubocop/cop/rails/skips_model_validations.rb +4 -2
  40. data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +1 -1
  41. data/lib/rubocop/cop/rails/strong_parameters_expect.rb +104 -0
  42. data/lib/rubocop/cop/rails/three_state_boolean_column.rb +2 -1
  43. data/lib/rubocop/cop/rails/time_zone.rb +13 -6
  44. data/lib/rubocop/cop/rails/transaction_exit_statement.rb +5 -0
  45. data/lib/rubocop/cop/rails/where_equals.rb +6 -1
  46. data/lib/rubocop/cop/rails/where_not.rb +6 -1
  47. data/lib/rubocop/cop/rails/where_range.rb +7 -2
  48. data/lib/rubocop/cop/rails_cops.rb +3 -0
  49. data/lib/rubocop/rails/migration_file_skippable.rb +54 -0
  50. data/lib/rubocop/rails/version.rb +1 -1
  51. data/lib/rubocop/rails.rb +0 -1
  52. data/lib/rubocop-rails.rb +3 -0
  53. metadata +8 -7
@@ -28,6 +28,8 @@ module RuboCop
28
28
  # Time.zone.now
29
29
  # Time.zone.parse('2015-03-02T19:05:37')
30
30
  # Time.zone.parse('2015-03-02T19:05:37Z') # Respect ISO 8601 format with timezone specifier.
31
+ # Time.parse('2015-03-02T19:05:37Z') # Also respects ISO 8601
32
+ # '2015-03-02T19:05:37Z'.to_time # Also respects ISO 8601
31
33
  #
32
34
  # @example EnforcedStyle: flexible (default)
33
35
  # # `flexible` allows usage of `in_time_zone` instead of `zone`.
@@ -67,6 +69,7 @@ module RuboCop
67
69
 
68
70
  def on_send(node)
69
71
  return if !node.receiver&.str_type? || !node.method?(:to_time)
72
+ return if attach_timezone_specifier?(node.receiver)
70
73
 
71
74
  add_offense(node.loc.selector, message: MSG_STRING_TO_TIME) do |corrector|
72
75
  corrector.replace(node, "Time.zone.parse(#{node.receiver.source})") unless node.csend_type?
@@ -94,11 +97,9 @@ module RuboCop
94
97
  end
95
98
 
96
99
  def autocorrect_time_new(node, corrector)
97
- if node.arguments?
98
- corrector.replace(node.loc.selector, 'local')
99
- else
100
- corrector.replace(node.loc.selector, 'now')
101
- end
100
+ replacement = replacement(node)
101
+
102
+ corrector.replace(node.loc.selector, replacement)
102
103
  end
103
104
 
104
105
  # remove redundant `.in_time_zone` from `Time.zone.now.in_time_zone`
@@ -180,7 +181,7 @@ module RuboCop
180
181
 
181
182
  def safe_method(method_name, node)
182
183
  if %w[new current].include?(method_name)
183
- node.arguments? ? 'local' : 'now'
184
+ replacement(node)
184
185
  else
185
186
  method_name
186
187
  end
@@ -256,6 +257,12 @@ module RuboCop
256
257
  pair.key.sym_type? && pair.key.value == :in && !pair.value.nil_type?
257
258
  end
258
259
  end
260
+
261
+ def replacement(node)
262
+ return 'now' unless node.arguments?
263
+
264
+ node.first_argument.str_type? ? 'parse' : 'local'
265
+ end
259
266
  end
260
267
  end
261
268
  end
@@ -15,6 +15,10 @@ module RuboCop
15
15
  #
16
16
  # If you are defining custom transaction methods, you can configure it with `TransactionMethods`.
17
17
  #
18
+ # NOTE: This cop is disabled on Rails >= 7.2 because transactions were restored
19
+ # to their historical behavior. In Rails 7.1, the behavior is controlled with
20
+ # the config `active_record.commit_transaction_on_non_local_return`.
21
+ #
18
22
  # @example
19
23
  # # bad
20
24
  # ApplicationRecord.transaction do
@@ -76,6 +80,7 @@ module RuboCop
76
80
  PATTERN
77
81
 
78
82
  def on_send(node)
83
+ return if target_rails_version >= 7.2
79
84
  return unless in_transaction_block?(node)
80
85
 
81
86
  exit_statements(node.parent.body).each do |statement_node|
@@ -74,6 +74,7 @@ module RuboCop
74
74
  range_between(node.loc.selector.begin_pos, node.source_range.end_pos)
75
75
  end
76
76
 
77
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
77
78
  def extract_column_and_value(template_node, value_node)
78
79
  value =
79
80
  case template_node.value
@@ -90,8 +91,12 @@ module RuboCop
90
91
  return
91
92
  end
92
93
 
93
- [Regexp.last_match(1), value]
94
+ column_qualifier = Regexp.last_match(1)
95
+ return if column_qualifier.count('.') > 1
96
+
97
+ [column_qualifier, value]
94
98
  end
99
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
95
100
 
96
101
  def build_good_method(method_name, column, value)
97
102
  if column.include?('.')
@@ -68,6 +68,7 @@ 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
@@ -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 ||= '.'
@@ -89,7 +89,7 @@ module RuboCop
89
89
 
90
90
  def where_not?(node)
91
91
  receiver = node.receiver
92
- receiver&.send_type? && receiver&.method?(:where)
92
+ receiver&.send_type? && receiver.method?(:where)
93
93
  end
94
94
 
95
95
  # rubocop:disable Metrics
@@ -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
 
@@ -7,9 +7,11 @@ require_relative 'mixin/database_type_resolvable'
7
7
  require_relative 'mixin/enforce_superclass'
8
8
  require_relative 'mixin/index_method'
9
9
  require_relative 'mixin/migrations_helper'
10
+ require_relative 'mixin/routes_helper'
10
11
  require_relative 'mixin/target_rails_version'
11
12
 
12
13
  require_relative 'rails/action_controller_flash_before_render'
14
+ require_relative 'rails/strong_parameters_expect'
13
15
  require_relative 'rails/action_controller_test_case'
14
16
  require_relative 'rails/action_filter'
15
17
  require_relative 'rails/action_order'
@@ -77,6 +79,7 @@ require_relative 'rails/link_to_blank'
77
79
  require_relative 'rails/mailer_name'
78
80
  require_relative 'rails/match_route'
79
81
  require_relative 'rails/migration_class_name'
82
+ require_relative 'rails/multiple_route_paths'
80
83
  require_relative 'rails/negate_include'
81
84
  require_relative 'rails/not_null_column'
82
85
  require_relative 'rails/order_by_id'
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Rails
5
+ # This module allows cops to detect and ignore files that have already been migrated
6
+ # by leveraging the `AllCops: MigratedSchemaVersion` configuration.
7
+ #
8
+ # [source,yaml]
9
+ # -----
10
+ # AllCops:
11
+ # MigratedSchemaVersion: '20241225000000'
12
+ # -----
13
+ #
14
+ # When applied to cops, it overrides the `add_global_offense` and `add_offense` methods,
15
+ # ensuring that cops skip processing if the file is determined to be a migrated file
16
+ # based on the schema version.
17
+ #
18
+ # @api private
19
+ module MigrationFileSkippable
20
+ def add_global_offense(message = nil, severity: nil)
21
+ return if already_migrated_file?
22
+
23
+ super if method(__method__).super_method
24
+ end
25
+
26
+ def add_offense(node_or_range, message: nil, severity: nil, &block)
27
+ return if already_migrated_file?
28
+
29
+ super if method(__method__).super_method
30
+ end
31
+
32
+ def self.apply_to_cops!
33
+ RuboCop::Cop::Registry.all.each { |cop| cop.prepend(MigrationFileSkippable) }
34
+ end
35
+
36
+ private
37
+
38
+ def already_migrated_file?
39
+ return false unless migrated_schema_version
40
+
41
+ match_data = File.basename(processed_source.file_path).match(/(?<timestamp>\d{14})/)
42
+ schema_version = match_data['timestamp'] if match_data
43
+
44
+ return false unless schema_version
45
+
46
+ schema_version <= migrated_schema_version.to_s # Ignore applied migration files.
47
+ end
48
+
49
+ def migrated_schema_version
50
+ @migrated_schema_version ||= config.for_all_cops.fetch('MigratedSchemaVersion', nil)
51
+ end
52
+ end
53
+ end
54
+ 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.26.0'
7
+ STRING = '2.29.1'
8
8
 
9
9
  def self.document_version
10
10
  STRING.match('\d+\.\d+').to_s
data/lib/rubocop/rails.rb CHANGED
@@ -5,7 +5,6 @@ module RuboCop
5
5
  module Rails
6
6
  PROJECT_ROOT = Pathname.new(__dir__).parent.parent.expand_path.freeze
7
7
  CONFIG_DEFAULT = PROJECT_ROOT.join('config', 'default.yml').freeze
8
- CONFIG = YAML.safe_load(CONFIG_DEFAULT.read, permitted_classes: [Regexp, Symbol]).freeze
9
8
 
10
9
  private_constant(:CONFIG_DEFAULT, :PROJECT_ROOT)
11
10
 
data/lib/rubocop-rails.rb CHANGED
@@ -15,6 +15,9 @@ RuboCop::Rails::Inject.defaults!
15
15
 
16
16
  require_relative 'rubocop/cop/rails_cops'
17
17
 
18
+ require_relative 'rubocop/rails/migration_file_skippable'
19
+ RuboCop::Rails::MigrationFileSkippable.apply_to_cops!
20
+
18
21
  RuboCop::Cop::Style::HashExcept.minimum_target_ruby_version(2.0)
19
22
 
20
23
  RuboCop::Cop::Style::InverseMethods.singleton_class.prepend(
metadata CHANGED
@@ -1,16 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.26.0
4
+ version: 2.29.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
8
8
  - Jonas Arvidsson
9
9
  - Yuji Nakayama
10
- autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2024-08-24 00:00:00.000000000 Z
12
+ date: 2025-01-25 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: activesupport
@@ -102,6 +101,7 @@ files:
102
101
  - lib/rubocop/cop/mixin/enforce_superclass.rb
103
102
  - lib/rubocop/cop/mixin/index_method.rb
104
103
  - lib/rubocop/cop/mixin/migrations_helper.rb
104
+ - lib/rubocop/cop/mixin/routes_helper.rb
105
105
  - lib/rubocop/cop/mixin/target_rails_version.rb
106
106
  - lib/rubocop/cop/rails/action_controller_flash_before_render.rb
107
107
  - lib/rubocop/cop/rails/action_controller_test_case.rb
@@ -171,6 +171,7 @@ files:
171
171
  - lib/rubocop/cop/rails/mailer_name.rb
172
172
  - lib/rubocop/cop/rails/match_route.rb
173
173
  - lib/rubocop/cop/rails/migration_class_name.rb
174
+ - lib/rubocop/cop/rails/multiple_route_paths.rb
174
175
  - lib/rubocop/cop/rails/negate_include.rb
175
176
  - lib/rubocop/cop/rails/not_null_column.rb
176
177
  - lib/rubocop/cop/rails/order_by_id.rb
@@ -214,6 +215,7 @@ files:
214
215
  - lib/rubocop/cop/rails/skips_model_validations.rb
215
216
  - lib/rubocop/cop/rails/squished_sql_heredocs.rb
216
217
  - lib/rubocop/cop/rails/strip_heredoc.rb
218
+ - lib/rubocop/cop/rails/strong_parameters_expect.rb
217
219
  - lib/rubocop/cop/rails/table_name_assignment.rb
218
220
  - lib/rubocop/cop/rails/three_state_boolean_column.rb
219
221
  - lib/rubocop/cop/rails/time_zone.rb
@@ -237,6 +239,7 @@ files:
237
239
  - lib/rubocop/cop/rails_cops.rb
238
240
  - lib/rubocop/rails.rb
239
241
  - lib/rubocop/rails/inject.rb
242
+ - lib/rubocop/rails/migration_file_skippable.rb
240
243
  - lib/rubocop/rails/schema_loader.rb
241
244
  - lib/rubocop/rails/schema_loader/schema.rb
242
245
  - lib/rubocop/rails/version.rb
@@ -247,10 +250,9 @@ metadata:
247
250
  homepage_uri: https://docs.rubocop.org/rubocop-rails/
248
251
  changelog_uri: https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md
249
252
  source_code_uri: https://github.com/rubocop/rubocop-rails/
250
- documentation_uri: https://docs.rubocop.org/rubocop-rails/2.26/
253
+ documentation_uri: https://docs.rubocop.org/rubocop-rails/2.29/
251
254
  bug_tracker_uri: https://github.com/rubocop/rubocop-rails/issues
252
255
  rubygems_mfa_required: 'true'
253
- post_install_message:
254
256
  rdoc_options: []
255
257
  require_paths:
256
258
  - lib
@@ -265,8 +267,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
265
267
  - !ruby/object:Gem::Version
266
268
  version: '0'
267
269
  requirements: []
268
- rubygems_version: 3.5.11
269
- signing_key:
270
+ rubygems_version: 3.6.2
270
271
  specification_version: 4
271
272
  summary: Automatic Rails code style checking tool.
272
273
  test_files: []