rubocop-rails 2.20.2 → 2.21.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 (30) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +55 -6
  3. data/lib/rubocop/cop/rails/action_controller_flash_before_render.rb +1 -1
  4. data/lib/rubocop/cop/rails/action_controller_test_case.rb +2 -2
  5. data/lib/rubocop/cop/rails/bulk_change_table.rb +20 -3
  6. data/lib/rubocop/cop/rails/dangerous_column_names.rb +439 -0
  7. data/lib/rubocop/cop/rails/date.rb +1 -1
  8. data/lib/rubocop/cop/rails/duplicate_association.rb +3 -0
  9. data/lib/rubocop/cop/rails/dynamic_find_by.rb +3 -3
  10. data/lib/rubocop/cop/rails/file_path.rb +4 -1
  11. data/lib/rubocop/cop/rails/freeze_time.rb +1 -1
  12. data/lib/rubocop/cop/rails/http_status.rb +4 -3
  13. data/lib/rubocop/cop/rails/i18n_lazy_lookup.rb +63 -13
  14. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +7 -8
  15. data/lib/rubocop/cop/rails/rake_environment.rb +20 -4
  16. data/lib/rubocop/cop/rails/redundant_active_record_all_method.rb +145 -0
  17. data/lib/rubocop/cop/rails/reversible_migration.rb +1 -1
  18. data/lib/rubocop/cop/rails/root_pathname_methods.rb +38 -4
  19. data/lib/rubocop/cop/rails/save_bang.rb +2 -2
  20. data/lib/rubocop/cop/rails/schema_comment.rb +16 -10
  21. data/lib/rubocop/cop/rails/select_map.rb +75 -0
  22. data/lib/rubocop/cop/rails/time_zone.rb +12 -5
  23. data/lib/rubocop/cop/rails/transaction_exit_statement.rb +29 -10
  24. data/lib/rubocop/cop/rails/unused_render_content.rb +68 -0
  25. data/lib/rubocop/cop/rails/where_exists.rb +0 -1
  26. data/lib/rubocop/cop/rails_cops.rb +4 -0
  27. data/lib/rubocop/rails/schema_loader.rb +1 -1
  28. data/lib/rubocop/rails/version.rb +1 -1
  29. data/lib/rubocop-rails.rb +8 -0
  30. metadata +7 -3
@@ -21,6 +21,7 @@ module RuboCop
21
21
  # # bad
22
22
  # Time.now
23
23
  # Time.parse('2015-03-02T19:05:37')
24
+ # '2015-03-02T19:05:37'.to_time
24
25
  #
25
26
  # # good
26
27
  # Time.current
@@ -44,19 +45,17 @@ module RuboCop
44
45
  extend AutoCorrector
45
46
 
46
47
  MSG = 'Do not use `%<current>s` without zone. Use `%<prefer>s` instead.'
47
-
48
48
  MSG_ACCEPTABLE = 'Do not use `%<current>s` without zone. Use one of %<prefer>s instead.'
49
-
50
49
  MSG_LOCALTIME = 'Do not use `Time.localtime` without offset or zone.'
50
+ MSG_STRING_TO_TIME = 'Do not use `String#to_time` without zone. Use `Time.zone.parse` instead.'
51
51
 
52
52
  GOOD_METHODS = %i[zone zone_default find_zone find_zone!].freeze
53
-
54
53
  DANGEROUS_METHODS = %i[now local new parse at].freeze
55
-
56
54
  ACCEPTED_METHODS = %i[in_time_zone utc getlocal xmlschema iso8601 jisx0301 rfc3339 httpdate to_i to_f].freeze
57
-
58
55
  TIMEZONE_SPECIFIER = /([A-Za-z]|[+-]\d{2}:?\d{2})\z/.freeze
59
56
 
57
+ RESTRICT_ON_SEND = %i[to_time].freeze
58
+
60
59
  def on_const(node)
61
60
  mod, klass = *node
62
61
  # we should only check core classes
@@ -66,6 +65,14 @@ module RuboCop
66
65
  check_time_node(klass, node.parent) if klass == :Time
67
66
  end
68
67
 
68
+ def on_send(node)
69
+ return if !node.receiver&.str_type? || !node.method?(:to_time)
70
+
71
+ add_offense(node.loc.selector, message: MSG_STRING_TO_TIME) do |corrector|
72
+ autocorrect(corrector, node)
73
+ end
74
+ end
75
+
69
76
  private
70
77
 
71
78
  def autocorrect(corrector, node)
@@ -13,6 +13,8 @@ module RuboCop
13
13
  # error when rollback is desired, and to use `next` when commit is
14
14
  # desired.
15
15
  #
16
+ # If you are defining custom transaction methods, you can configure it with `TransactionMethods`.
17
+ #
16
18
  # @example
17
19
  # # bad
18
20
  # ApplicationRecord.transaction do
@@ -50,12 +52,16 @@ module RuboCop
50
52
  # # Commit
51
53
  # next if user.active?
52
54
  # end
55
+ #
56
+ # @example TransactionMethods: ["custom_transaction"]
57
+ # # bad
58
+ # CustomModel.custom_transaction do
59
+ # return if user.active?
60
+ # end
61
+ #
53
62
  class TransactionExitStatement < Base
54
- MSG = <<~MSG.chomp
55
- Exit statement `%<statement>s` is not allowed. Use `raise` (rollback) or `next` (commit).
56
- MSG
57
-
58
- RESTRICT_ON_SEND = %i[transaction with_lock].freeze
63
+ MSG = 'Exit statement `%<statement>s` is not allowed. Use `raise` (rollback) or `next` (commit).'
64
+ BUILT_IN_TRANSACTION_METHODS = %i[transaction with_lock].freeze
59
65
 
60
66
  def_node_search :exit_statements, <<~PATTERN
61
67
  ({return | break | send nil? :throw} ...)
@@ -70,10 +76,9 @@ module RuboCop
70
76
  PATTERN
71
77
 
72
78
  def on_send(node)
73
- return unless (parent = node.parent)
74
- return unless parent.block_type? && parent.body
79
+ return unless in_transaction_block?(node)
75
80
 
76
- exit_statements(parent.body).each do |statement_node|
81
+ exit_statements(node.parent.body).each do |statement_node|
77
82
  next if statement_node.break_type? && nested_block?(statement_node)
78
83
 
79
84
  statement = statement(statement_node)
@@ -85,6 +90,13 @@ module RuboCop
85
90
 
86
91
  private
87
92
 
93
+ def in_transaction_block?(node)
94
+ return false unless transaction_method_name?(node.method_name)
95
+ return false unless (parent = node.parent)
96
+
97
+ parent.block_type? && parent.body
98
+ end
99
+
88
100
  def statement(statement_node)
89
101
  if statement_node.return_type?
90
102
  'return'
@@ -96,9 +108,16 @@ module RuboCop
96
108
  end
97
109
 
98
110
  def nested_block?(statement_node)
99
- block_node = statement_node.ancestors.find(&:block_type?)
111
+ name = statement_node.ancestors.find(&:block_type?).children.first.method_name
112
+ !transaction_method_name?(name)
113
+ end
114
+
115
+ def transaction_method_name?(method_name)
116
+ BUILT_IN_TRANSACTION_METHODS.include?(method_name) || transaction_method?(method_name)
117
+ end
100
118
 
101
- RESTRICT_ON_SEND.none? { |name| block_node.method?(name) }
119
+ def transaction_method?(method_name)
120
+ cop_config.fetch('TransactionMethods', []).include?(method_name.to_s)
102
121
  end
103
122
  end
104
123
  end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # If you try to render content along with a non-content status code (100-199, 204, 205, or 304),
7
+ # it will be dropped from the response.
8
+ #
9
+ # This cop checks for uses of `render` which specify both body content and a non-content status.
10
+ #
11
+ # @example
12
+ # # bad
13
+ # render 'foo', status: :continue
14
+ # render status: 100, plain: 'Ruby!'
15
+ #
16
+ # # good
17
+ # render status: :continue
18
+ # render status: 100
19
+ class UnusedRenderContent < Base
20
+ extend AutoCorrector
21
+ include RangeHelp
22
+
23
+ MSG = 'Do not specify body content for a response with a non-content status code'
24
+ RESTRICT_ON_SEND = %i[render].freeze
25
+ NON_CONTENT_STATUS_CODES = Set[*100..199, 204, 205, 304] & ::Rack::Utils::SYMBOL_TO_STATUS_CODE.values
26
+ NON_CONTENT_STATUSES = Set[
27
+ *::Rack::Utils::SYMBOL_TO_STATUS_CODE.invert.fetch_values(*NON_CONTENT_STATUS_CODES)
28
+ ]
29
+ BODY_OPTIONS = Set[
30
+ :action,
31
+ :body,
32
+ :content_type,
33
+ :file,
34
+ :html,
35
+ :inline,
36
+ :json,
37
+ :js,
38
+ :layout,
39
+ :plain,
40
+ :raw,
41
+ :template,
42
+ :text,
43
+ :xml
44
+ ]
45
+
46
+ def_node_matcher :non_content_status?, <<~PATTERN
47
+ (pair
48
+ (sym :status)
49
+ {(sym NON_CONTENT_STATUSES) (int NON_CONTENT_STATUS_CODES)}
50
+ )
51
+ PATTERN
52
+
53
+ def_node_matcher :unused_render_content?, <<~PATTERN
54
+ (send nil? :render {
55
+ (hash <#non_content_status? $(pair (sym BODY_OPTIONS) _) ...>) |
56
+ $({str sym} _) (hash <#non_content_status? ...>)
57
+ })
58
+ PATTERN
59
+
60
+ def on_send(node)
61
+ unused_render_content?(node) do |unused_content_node|
62
+ add_offense(unused_content_node)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -39,7 +39,6 @@ module RuboCop
39
39
  # # bad
40
40
  # User.exists?(name: 'john')
41
41
  # User.exists?(['name = ?', 'john'])
42
- # User.exists?('name = ?', 'john')
43
42
  # user.posts.exists?(published: true)
44
43
  #
45
44
  # # good
@@ -32,6 +32,7 @@ require_relative 'rails/bulk_change_table'
32
32
  require_relative 'rails/compact_blank'
33
33
  require_relative 'rails/content_tag'
34
34
  require_relative 'rails/create_table_with_timestamps'
35
+ require_relative 'rails/dangerous_column_names'
35
36
  require_relative 'rails/date'
36
37
  require_relative 'rails/default_scope'
37
38
  require_relative 'rails/delegate'
@@ -87,6 +88,7 @@ require_relative 'rails/presence'
87
88
  require_relative 'rails/present'
88
89
  require_relative 'rails/rake_environment'
89
90
  require_relative 'rails/read_write_attribute'
91
+ require_relative 'rails/redundant_active_record_all_method'
90
92
  require_relative 'rails/redundant_allow_nil'
91
93
  require_relative 'rails/redundant_foreign_key'
92
94
  require_relative 'rails/redundant_presence_validation_on_belongs_to'
@@ -110,6 +112,7 @@ require_relative 'rails/safe_navigation_with_blank'
110
112
  require_relative 'rails/save_bang'
111
113
  require_relative 'rails/schema_comment'
112
114
  require_relative 'rails/scope_args'
115
+ require_relative 'rails/select_map'
113
116
  require_relative 'rails/short_i18n'
114
117
  require_relative 'rails/skips_model_validations'
115
118
  require_relative 'rails/squished_sql_heredocs'
@@ -126,6 +129,7 @@ require_relative 'rails/uniq_before_pluck'
126
129
  require_relative 'rails/unique_validation_without_index'
127
130
  require_relative 'rails/unknown_env'
128
131
  require_relative 'rails/unused_ignored_columns'
132
+ require_relative 'rails/unused_render_content'
129
133
  require_relative 'rails/validation'
130
134
  require_relative 'rails/where_equals'
131
135
  require_relative 'rails/where_exists'
@@ -43,7 +43,7 @@ module RuboCop
43
43
  return unless path
44
44
 
45
45
  ast = parse(path, target_ruby_version)
46
- Schema.new(ast)
46
+ Schema.new(ast) if ast
47
47
  end
48
48
 
49
49
  def parse(path, target_ruby_version)
@@ -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.20.2'
7
+ STRING = '2.21.0'
8
8
 
9
9
  def self.document_version
10
10
  STRING.match('\d+\.\d+').to_s
data/lib/rubocop-rails.rb CHANGED
@@ -17,6 +17,14 @@ require_relative 'rubocop/cop/rails_cops'
17
17
 
18
18
  RuboCop::Cop::Style::HashExcept.minimum_target_ruby_version(2.0)
19
19
 
20
+ RuboCop::Cop::Style::InverseMethods.singleton_class.prepend(
21
+ Module.new do
22
+ def autocorrect_incompatible_with
23
+ super.push(RuboCop::Cop::Rails::NegateInclude)
24
+ end
25
+ end
26
+ )
27
+
20
28
  RuboCop::Cop::Style::MethodCallWithArgsParentheses.singleton_class.prepend(
21
29
  Module.new do
22
30
  def autocorrect_incompatible_with
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.20.2
4
+ version: 2.21.0
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: 2023-06-19 00:00:00.000000000 Z
13
+ date: 2023-09-09 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -106,6 +106,7 @@ files:
106
106
  - lib/rubocop/cop/rails/compact_blank.rb
107
107
  - lib/rubocop/cop/rails/content_tag.rb
108
108
  - lib/rubocop/cop/rails/create_table_with_timestamps.rb
109
+ - lib/rubocop/cop/rails/dangerous_column_names.rb
109
110
  - lib/rubocop/cop/rails/date.rb
110
111
  - lib/rubocop/cop/rails/default_scope.rb
111
112
  - lib/rubocop/cop/rails/delegate.rb
@@ -161,6 +162,7 @@ files:
161
162
  - lib/rubocop/cop/rails/present.rb
162
163
  - lib/rubocop/cop/rails/rake_environment.rb
163
164
  - lib/rubocop/cop/rails/read_write_attribute.rb
165
+ - lib/rubocop/cop/rails/redundant_active_record_all_method.rb
164
166
  - lib/rubocop/cop/rails/redundant_allow_nil.rb
165
167
  - lib/rubocop/cop/rails/redundant_foreign_key.rb
166
168
  - lib/rubocop/cop/rails/redundant_presence_validation_on_belongs_to.rb
@@ -184,6 +186,7 @@ files:
184
186
  - lib/rubocop/cop/rails/save_bang.rb
185
187
  - lib/rubocop/cop/rails/schema_comment.rb
186
188
  - lib/rubocop/cop/rails/scope_args.rb
189
+ - lib/rubocop/cop/rails/select_map.rb
187
190
  - lib/rubocop/cop/rails/short_i18n.rb
188
191
  - lib/rubocop/cop/rails/skips_model_validations.rb
189
192
  - lib/rubocop/cop/rails/squished_sql_heredocs.rb
@@ -200,6 +203,7 @@ files:
200
203
  - lib/rubocop/cop/rails/unique_validation_without_index.rb
201
204
  - lib/rubocop/cop/rails/unknown_env.rb
202
205
  - lib/rubocop/cop/rails/unused_ignored_columns.rb
206
+ - lib/rubocop/cop/rails/unused_render_content.rb
203
207
  - lib/rubocop/cop/rails/validation.rb
204
208
  - lib/rubocop/cop/rails/where_equals.rb
205
209
  - lib/rubocop/cop/rails/where_exists.rb
@@ -219,7 +223,7 @@ metadata:
219
223
  homepage_uri: https://docs.rubocop.org/rubocop-rails/
220
224
  changelog_uri: https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md
221
225
  source_code_uri: https://github.com/rubocop/rubocop-rails/
222
- documentation_uri: https://docs.rubocop.org/rubocop-rails/2.20/
226
+ documentation_uri: https://docs.rubocop.org/rubocop-rails/2.21/
223
227
  bug_tracker_uri: https://github.com/rubocop/rubocop-rails/issues
224
228
  rubygems_mfa_required: 'true'
225
229
  post_install_message: