rubocop-rails 2.20.2 → 2.21.1

Sign up to get free protection for your applications and to get access to all the features.
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 +146 -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
+ corrector.replace(node, "Time.zone.parse(#{node.receiver.source})")
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.1'
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.1
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-14 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: