rubocop-rails 2.25.0 → 2.25.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cad5e6d0c6f188b6ff87adb04fbfb73c7c574b901de45256eb7fa6e50b7a136d
4
- data.tar.gz: c8ab8f1d1c3284054af5847231dd996df24ee5441f638f95bc7e32420a3baf04
3
+ metadata.gz: b55703b258e4df9bae3a9a8c1b77a4fa143af6af3ed9b1b22118fd839d1ce06c
4
+ data.tar.gz: 24568d7d8d22d69469ae9a4aaf426ea45bf848989604a8744ab6493bc0b222a3
5
5
  SHA512:
6
- metadata.gz: ea0ebe45e988d115aa45d7bdba2b728b0583e1e2d996d43af424eb8abc17ced35b528741fcc47b8b258de52edd2fb7bc1c92dd609b49ddeeaaaf26bce123e783
7
- data.tar.gz: 7eb06cfce19f2a4ba78c6d571c65cf386e211b48ca2c9b5b9ca436ec9055e49f9737cbb3f9ce1b44ab432de87121295439effc59f093446cea88199bd08ba8a4
6
+ metadata.gz: 47d5668b744967fc740b47552e9d05068fc5ce5c209a4a994a429262a0628b13e0f1e48d6a39018430fb7e874f88e4badbd9427219b9a77220e522d6706b1c3c
7
+ data.tar.gz: 242030d6fe9063d51f18e98869e2a048a4b7b847f0f6a25937fc3d9781dbb7749de8b015b3fa0b4933511b83487ad060fbdbf9adb7942a20bfc035d5fc9e2f04
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # RuboCop Rails
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/rubocop-rails.svg)](https://badge.fury.io/rb/rubocop-rails)
4
- [![CircleCI](https://circleci.com/gh/rubocop/rubocop-rails.svg?style=svg)](https://circleci.com/gh/rubocop/rubocop-rails)
4
+ [![CI](https://github.com/rubocop/rubocop-rails/actions/workflows/test.yml/badge.svg)](https://github.com/rubocop/rubocop-rails/actions/workflows/test.yml)
5
5
 
6
6
  A [RuboCop](https://github.com/rubocop/rubocop) extension focused on enforcing Rails best practices and coding conventions.
7
7
 
data/config/default.yml CHANGED
@@ -1018,8 +1018,9 @@ Rails/SkipsModelValidations:
1018
1018
  See reference for more information.
1019
1019
  Reference: 'https://guides.rubyonrails.org/active_record_validations.html#skipping-validations'
1020
1020
  Enabled: true
1021
+ Safe: false
1021
1022
  VersionAdded: '0.47'
1022
- VersionChanged: '2.7'
1023
+ VersionChanged: '2.25'
1023
1024
  ForbiddenMethods:
1024
1025
  - decrement!
1025
1026
  - decrement_counter
@@ -1226,6 +1227,7 @@ Rails/WhereRange:
1226
1227
  Description: 'Use ranges in `where` instead of manually constructing SQL.'
1227
1228
  StyleGuide: 'https://rails.rubystyle.guide/#where-ranges'
1228
1229
  Enabled: pending
1230
+ SafeAutoCorrect: false
1229
1231
  VersionAdded: '2.25'
1230
1232
 
1231
1233
  # Accept `redirect_to(...) and return` and similar cases.
@@ -113,8 +113,10 @@ module RuboCop
113
113
  MYSQL_COMBINABLE_ALTER_METHODS = %i[rename_column add_index remove_index].freeze
114
114
 
115
115
  POSTGRESQL_COMBINABLE_TRANSFORMATIONS = %i[change_default].freeze
116
+ POSTGRESQL_COMBINABLE_TRANSFORMATIONS_SINCE_6_1 = %i[change_null].freeze
116
117
 
117
118
  POSTGRESQL_COMBINABLE_ALTER_METHODS = %i[change_column_default].freeze
119
+ POSTGRESQL_COMBINABLE_ALTER_METHODS_SINCE_6_1 = %i[change_column_null].freeze
118
120
 
119
121
  def on_def(node)
120
122
  return unless support_bulk_alter?
@@ -196,7 +198,9 @@ module RuboCop
196
198
  when MYSQL
197
199
  COMBINABLE_ALTER_METHODS + MYSQL_COMBINABLE_ALTER_METHODS
198
200
  when POSTGRESQL
199
- COMBINABLE_ALTER_METHODS + POSTGRESQL_COMBINABLE_ALTER_METHODS
201
+ result = COMBINABLE_ALTER_METHODS + POSTGRESQL_COMBINABLE_ALTER_METHODS
202
+ result += POSTGRESQL_COMBINABLE_ALTER_METHODS_SINCE_6_1 if target_rails_version >= 6.1
203
+ result
200
204
  end
201
205
  end
202
206
 
@@ -205,7 +209,9 @@ module RuboCop
205
209
  when MYSQL
206
210
  COMBINABLE_TRANSFORMATIONS + MYSQL_COMBINABLE_TRANSFORMATIONS
207
211
  when POSTGRESQL
208
- COMBINABLE_TRANSFORMATIONS + POSTGRESQL_COMBINABLE_TRANSFORMATIONS
212
+ result = COMBINABLE_TRANSFORMATIONS + POSTGRESQL_COMBINABLE_TRANSFORMATIONS
213
+ result += POSTGRESQL_COMBINABLE_TRANSFORMATIONS_SINCE_6_1 if target_rails_version >= 6.1
214
+ result
209
215
  end
210
216
  end
211
217
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # Checks for calls to `link_to` that contain a
6
+ # Checks for calls to `link_to`, `link_to_if`, and `link_to_unless` methods that contain a
7
7
  # `target: '_blank'` but no `rel: 'noopener'`. This can be a security
8
8
  # risk as the loaded page will have control over the previous page
9
9
  # and could change its location for phishing purposes.
@@ -24,7 +24,7 @@ module RuboCop
24
24
  extend AutoCorrector
25
25
 
26
26
  MSG = 'Specify a `:rel` option containing noopener.'
27
- RESTRICT_ON_SEND = %i[link_to].freeze
27
+ RESTRICT_ON_SEND = %i[link_to link_to_if link_to_unless].freeze
28
28
 
29
29
  def_node_matcher :blank_target?, <<~PATTERN
30
30
  (pair {(sym :target) (str "target")} {(str "_blank") (sym :_blank)})
@@ -136,6 +136,8 @@ module RuboCop
136
136
 
137
137
  def check_change_table(node)
138
138
  change_table?(node) do |table|
139
+ next unless node.body
140
+
139
141
  children = node.body.begin_type? ? node.body.children : [node.body]
140
142
  children.each do |child|
141
143
  check_add_column_in_change_table(child, table)
@@ -9,6 +9,9 @@ module RuboCop
9
9
  #
10
10
  # Methods may be ignored from this rule by configuring a `AllowedMethods`.
11
11
  #
12
+ # @safety
13
+ # This cop is unsafe if the receiver object is not an Active Record object.
14
+ #
12
15
  # @example
13
16
  # # bad
14
17
  # Article.first.decrement!(:view_count)
@@ -8,6 +8,7 @@ module RuboCop
8
8
  # @example
9
9
  # # bad
10
10
  # validates_acceptance_of :foo
11
+ # validates_comparison_of :foo
11
12
  # validates_confirmation_of :foo
12
13
  # validates_exclusion_of :foo
13
14
  # validates_format_of :foo
@@ -22,6 +23,7 @@ module RuboCop
22
23
  # # good
23
24
  # validates :foo, acceptance: true
24
25
  # validates :foo, confirmation: true
26
+ # validates :foo, comparison: true
25
27
  # validates :foo, exclusion: true
26
28
  # validates :foo, format: true
27
29
  # validates :foo, inclusion: true
@@ -39,6 +41,7 @@ module RuboCop
39
41
 
40
42
  TYPES = %w[
41
43
  acceptance
44
+ comparison
42
45
  confirmation
43
46
  exclusion
44
47
  format
@@ -6,6 +6,14 @@ module RuboCop
6
6
  # Identifies places where manually constructed SQL
7
7
  # in `where` can be replaced with ranges.
8
8
  #
9
+ # @safety
10
+ # This cop's autocorrection is unsafe because it can change the query
11
+ # by explicitly attaching the column to the wrong table.
12
+ # For example, `Booking.joins(:events).where('end_at < ?', Time.current)` will correctly
13
+ # implicitly attach the `end_at` column to the `events` table. But when autocorrected to
14
+ # `Booking.joins(:events).where(end_at: ...Time.current)`, it will now be incorrectly
15
+ # explicitly attached to the `bookings` table.
16
+ #
9
17
  # @example
10
18
  # # bad
11
19
  # User.where('age >= ?', 18)
@@ -37,17 +45,17 @@ module RuboCop
37
45
  RESTRICT_ON_SEND = %i[where not].freeze
38
46
 
39
47
  # column >= ?
40
- GTEQ_ANONYMOUS_RE = /\A([\w.]+)\s+>=\s+\?\z/.freeze
48
+ GTEQ_ANONYMOUS_RE = /\A\s*([\w.]+)\s+>=\s+\?\s*\z/.freeze
41
49
  # column <[=] ?
42
- LTEQ_ANONYMOUS_RE = /\A([\w.]+)\s+(<=?)\s+\?\z/.freeze
50
+ LTEQ_ANONYMOUS_RE = /\A\s*([\w.]+)\s+(<=?)\s+\?\s*\z/.freeze
43
51
  # column >= ? AND column <[=] ?
44
- RANGE_ANONYMOUS_RE = /\A([\w.]+)\s+>=\s+\?\s+AND\s+\1\s+(<=?)\s+\?\z/i.freeze
52
+ RANGE_ANONYMOUS_RE = /\A\s*([\w.]+)\s+>=\s+\?\s+AND\s+\1\s+(<=?)\s+\?\s*\z/i.freeze
45
53
  # column >= :value
46
- GTEQ_NAMED_RE = /\A([\w.]+)\s+>=\s+:(\w+)\z/.freeze
54
+ GTEQ_NAMED_RE = /\A\s*([\w.]+)\s+>=\s+:(\w+)\s*\z/.freeze
47
55
  # column <[=] :value
48
- LTEQ_NAMED_RE = /\A([\w.]+)\s+(<=?)\s+:(\w+)\z/.freeze
56
+ LTEQ_NAMED_RE = /\A\s*([\w.]+)\s+(<=?)\s+:(\w+)\s*\z/.freeze
49
57
  # column >= :value1 AND column <[=] :value2
50
- RANGE_NAMED_RE = /\A([\w.]+)\s+>=\s+:(\w+)\s+AND\s+\1\s+(<=?)\s+:(\w+)\z/i.freeze
58
+ RANGE_NAMED_RE = /\A\s*([\w.]+)\s+>=\s+:(\w+)\s+AND\s+\1\s+(<=?)\s+:(\w+)\s*\z/i.freeze
51
59
 
52
60
  minimum_target_ruby_version 2.6
53
61
  minimum_target_rails_version 6.0
@@ -86,47 +94,63 @@ module RuboCop
86
94
 
87
95
  # rubocop:disable Metrics
88
96
  def extract_column_and_value(template_node, values_node)
89
- value =
90
- case template_node.value
91
- when GTEQ_ANONYMOUS_RE
92
- "#{values_node[0].source}.."
93
- when LTEQ_ANONYMOUS_RE
94
- range_operator = range_operator(Regexp.last_match(2))
95
- "#{range_operator}#{values_node[0].source}" if target_ruby_version >= 2.7
96
- when RANGE_ANONYMOUS_RE
97
- if values_node.size >= 2
98
- range_operator = range_operator(Regexp.last_match(2))
99
- "#{values_node[0].source}#{range_operator}#{values_node[1].source}"
100
- end
101
- when GTEQ_NAMED_RE
102
- value_node = values_node[0]
97
+ case template_node.value
98
+ when GTEQ_ANONYMOUS_RE
99
+ lhs = values_node[0]
100
+ operator = '..'
101
+ when LTEQ_ANONYMOUS_RE
102
+ if target_ruby_version >= 2.7
103
+ operator = range_operator(Regexp.last_match(2))
104
+ rhs = values_node[0]
105
+ end
106
+ when RANGE_ANONYMOUS_RE
107
+ if values_node.size >= 2
108
+ lhs = values_node[0]
109
+ operator = range_operator(Regexp.last_match(2))
110
+ rhs = values_node[1]
111
+ end
112
+ when GTEQ_NAMED_RE
113
+ value_node = values_node[0]
103
114
 
104
- if value_node.hash_type?
105
- pair = find_pair(value_node, Regexp.last_match(2))
106
- "#{pair.value.source}.." if pair
107
- end
108
- when LTEQ_NAMED_RE
109
- value_node = values_node[0]
110
-
111
- if value_node.hash_type?
112
- pair = find_pair(value_node, Regexp.last_match(2))
113
- if pair && target_ruby_version >= 2.7
114
- range_operator = range_operator(Regexp.last_match(2))
115
- "#{range_operator}#{pair.value.source}"
116
- end
115
+ if value_node.hash_type?
116
+ pair = find_pair(value_node, Regexp.last_match(2))
117
+ lhs = pair.value
118
+ operator = '..'
119
+ end
120
+ when LTEQ_NAMED_RE
121
+ value_node = values_node[0]
122
+
123
+ if value_node.hash_type?
124
+ pair = find_pair(value_node, Regexp.last_match(2))
125
+ if pair && target_ruby_version >= 2.7
126
+ operator = range_operator(Regexp.last_match(2))
127
+ rhs = pair.value
117
128
  end
118
- when RANGE_NAMED_RE
119
- value_node = values_node[0]
120
-
121
- if value_node.hash_type?
122
- range_operator = range_operator(Regexp.last_match(3))
123
- pair1 = find_pair(value_node, Regexp.last_match(2))
124
- pair2 = find_pair(value_node, Regexp.last_match(4))
125
- "#{pair1.value.source}#{range_operator}#{pair2.value.source}" if pair1 && pair2
129
+ end
130
+ when RANGE_NAMED_RE
131
+ value_node = values_node[0]
132
+
133
+ if value_node.hash_type?
134
+ pair1 = find_pair(value_node, Regexp.last_match(2))
135
+ pair2 = find_pair(value_node, Regexp.last_match(4))
136
+
137
+ if pair1 && pair2
138
+ lhs = pair1.value
139
+ operator = range_operator(Regexp.last_match(3))
140
+ rhs = pair2.value
126
141
  end
127
142
  end
143
+ end
128
144
 
129
- [Regexp.last_match(1), value] if value
145
+ if lhs
146
+ lhs_source = parentheses_needed?(lhs) ? "(#{lhs.source})" : lhs.source
147
+ end
148
+
149
+ if rhs
150
+ rhs_source = parentheses_needed?(rhs) ? "(#{rhs.source})" : rhs.source
151
+ end
152
+
153
+ [Regexp.last_match(1), "#{lhs_source}#{operator}#{rhs_source}"] if operator
130
154
  end
131
155
  # rubocop:enable Metrics
132
156
 
@@ -151,6 +175,23 @@ module RuboCop
151
175
  "#{method_name}(#{column}: #{value})"
152
176
  end
153
177
  end
178
+
179
+ def parentheses_needed?(node)
180
+ !parentheses_not_needed?(node)
181
+ end
182
+
183
+ def parentheses_not_needed?(node)
184
+ node.variable? ||
185
+ node.literal? ||
186
+ node.reference? ||
187
+ node.const_type? ||
188
+ node.begin_type? ||
189
+ parenthesized_call_node?(node)
190
+ end
191
+
192
+ def parenthesized_call_node?(node)
193
+ node.call_type? && (node.arguments.empty? || node.parenthesized_call?)
194
+ end
154
195
  end
155
196
  end
156
197
  end
@@ -178,7 +178,7 @@ module RuboCop
178
178
  attr_reader :table_name
179
179
 
180
180
  def initialize(node)
181
- super(node)
181
+ super
182
182
 
183
183
  @table_name = node.first_argument.value
184
184
  @columns, @expression = build_columns_or_expr(node.arguments[1])
@@ -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.0'
7
+ STRING = '2.25.1'
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.0
4
+ version: 2.25.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: 2024-05-17 00:00:00.000000000 Z
13
+ date: 2024-06-29 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -264,7 +264,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
264
264
  - !ruby/object:Gem::Version
265
265
  version: '0'
266
266
  requirements: []
267
- rubygems_version: 3.5.3
267
+ rubygems_version: 3.5.11
268
268
  signing_key:
269
269
  specification_version: 4
270
270
  summary: Automatic Rails code style checking tool.