rubocop-rails 2.13.1 → 2.13.2

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: 624c6bfb8dc9c5db0f6dd6bec835bd71e5e5a7aadc298342c15faae187226079
4
- data.tar.gz: 4354d39a8367f0e4cb46b5a890cdd0836bfff6d838b5ae320b3df3a480f529af
3
+ metadata.gz: 87ab88a596e8f8dbe2ef0ded9a93ae1ceba10572ad41fc6b4e1b0b684cf68110
4
+ data.tar.gz: 4bc8502424aa32efec36f06ca475b7a3918b160060f76aa65eba39bfa5a31947
5
5
  SHA512:
6
- metadata.gz: 19863e8b5b71b4403d66b46e73ed41ceb1953d2a68996fbcc800ab4c06fcf4dfebadf3907f62d2c575b002223a95fa67fce2412c01fa42b6234848c2791b37e9
7
- data.tar.gz: 1e3d14e3240f7fdb9182529865ee8257cf19368bac19c33abfba44b0a3b63c54e64457f73725e6c629a5846ea402a96e650f7d6ce0e1943386c857d6a8642d7b
6
+ metadata.gz: 27016cd823ac6eb75ddb06f97c613fea178b29dc8cadac6289c803a9745ccbe2ffd7f7799c82b1a9ddd74f08ab162fcb50acf9a491a5841f1d09931eec8145fa
7
+ data.tar.gz: 95c826339433a0a87f296676216e62b493cdc4d5b67ac73c400659194d3a54e874554d0431c3cbea02316d4265cd870755320ed5f5fd6b42722fdd17feba041e
data/config/default.yml CHANGED
@@ -453,6 +453,7 @@ Rails/InverseOf:
453
453
  Description: 'Checks for associations where the inverse cannot be determined automatically.'
454
454
  Enabled: true
455
455
  VersionAdded: '0.52'
456
+ IgnoreScopes: false
456
457
  Include:
457
458
  - app/models/**/*.rb
458
459
 
@@ -627,6 +628,7 @@ Rails/RedundantForeignKey:
627
628
  Rails/RedundantPresenceValidationOnBelongsTo:
628
629
  Description: 'Checks for redundant presence validation on belongs_to association.'
629
630
  Enabled: pending
631
+ SafeAutoCorrect: false
630
632
  VersionAdded: '2.13'
631
633
 
632
634
  Rails/RedundantReceiverInWithOptions:
@@ -702,15 +704,17 @@ Rails/ReversibleMigration:
702
704
  Reference: 'https://api.rubyonrails.org/classes/ActiveRecord/Migration/CommandRecorder.html'
703
705
  Enabled: true
704
706
  VersionAdded: '0.47'
707
+ VersionChanged: '2.13'
705
708
  Include:
706
- - db/migrate/*.rb
709
+ - db/**/*.rb
707
710
 
708
711
  Rails/ReversibleMigrationMethodDefinition:
709
712
  Description: 'Checks whether the migration implements either a `change` method or both an `up` and a `down` method.'
710
713
  Enabled: false
711
714
  VersionAdded: '2.10'
715
+ VersionChanged: '2.13'
712
716
  Include:
713
- - db/migrate/*.rb
717
+ - db/**/*.rb
714
718
 
715
719
  Rails/RootJoinChain:
716
720
  Description: 'Use a single `#join` instead of chaining on `Rails.root` or `Rails.public_path`.'
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # Common functionality for cops working with migrations
6
+ module MigrationsHelper
7
+ extend NodePattern::Macros
8
+
9
+ def_node_matcher :migration_class?, <<~PATTERN
10
+ (class
11
+ (const nil? _)
12
+ (send
13
+ (const (const {nil? cbase} :ActiveRecord) :Migration)
14
+ :[]
15
+ (float _))
16
+ _)
17
+ PATTERN
18
+
19
+ def in_migration?(node)
20
+ node.each_ancestor(:class).any? do |class_node|
21
+ migration_class?(class_node)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -10,25 +10,21 @@ module RuboCop
10
10
  # blank check of block arguments to the receiver object.
11
11
  #
12
12
  # For example, `[[1, 2], [3, nil]].reject { |first, second| second.blank? }` and
13
- # `[[1, 2], [3, nil]].compact_blank` are not compatible. The same is true for `empty?`.
13
+ # `[[1, 2], [3, nil]].compact_blank` are not compatible. The same is true for `blank?`.
14
14
  # This will work fine when the receiver is a hash object.
15
15
  #
16
16
  # @example
17
17
  #
18
18
  # # bad
19
19
  # collection.reject(&:blank?)
20
- # collection.reject(&:empty?)
21
20
  # collection.reject { |_k, v| v.blank? }
22
- # collection.reject { |_k, v| v.empty? }
23
21
  #
24
22
  # # good
25
23
  # collection.compact_blank
26
24
  #
27
25
  # # bad
28
26
  # collection.reject!(&:blank?)
29
- # collection.reject!(&:empty?)
30
27
  # collection.reject! { |_k, v| v.blank? }
31
- # collection.reject! { |_k, v| v.empty? }
32
28
  #
33
29
  # # good
34
30
  # collection.compact_blank!
@@ -48,13 +44,13 @@ module RuboCop
48
44
  (send _ {:reject :reject!})
49
45
  $(args ...)
50
46
  (send
51
- $(lvar _) {:blank? :empty?}))
47
+ $(lvar _) :blank?))
52
48
  PATTERN
53
49
 
54
50
  def_node_matcher :reject_with_block_pass?, <<~PATTERN
55
51
  (send _ {:reject :reject!}
56
52
  (block_pass
57
- (sym {:blank? :empty?})))
53
+ (sym :blank?)))
58
54
  PATTERN
59
55
 
60
56
  def on_send(node)
@@ -73,12 +69,17 @@ module RuboCop
73
69
  return true if reject_with_block_pass?(node)
74
70
 
75
71
  if (arguments, receiver_in_block = reject_with_block?(node.parent))
76
- return arguments.length == 1 || use_hash_value_block_argument?(arguments, receiver_in_block)
72
+ return use_single_value_block_argument?(arguments, receiver_in_block) ||
73
+ use_hash_value_block_argument?(arguments, receiver_in_block)
77
74
  end
78
75
 
79
76
  false
80
77
  end
81
78
 
79
+ def use_single_value_block_argument?(arguments, receiver_in_block)
80
+ arguments.length == 1 && arguments[0].source == receiver_in_block.source
81
+ end
82
+
82
83
  def use_hash_value_block_argument?(arguments, receiver_in_block)
83
84
  arguments.length == 2 && arguments[1].source == receiver_in_block.source
84
85
  end
@@ -26,7 +26,8 @@ module RuboCop
26
26
  RESTRICT_ON_SEND = %i[+ -].freeze
27
27
 
28
28
  DURATIONS = Set[:second, :seconds, :minute, :minutes, :hour, :hours,
29
- :day, :days, :week, :weeks, :fortnight, :fortnights]
29
+ :day, :days, :week, :weeks, :fortnight, :fortnights,
30
+ :month, :months, :year, :years]
30
31
 
31
32
  # @!method duration_arithmetic_argument?(node)
32
33
  # Match duration subtraction or addition with current time.
@@ -126,6 +126,18 @@ module RuboCop
126
126
  # has_many :physicians, through: :appointments
127
127
  # end
128
128
  #
129
+ # @example IgnoreScopes: false (default)
130
+ # # bad
131
+ # class Blog < ApplicationRecord
132
+ # has_many :posts, -> { order(published_at: :desc) }
133
+ # end
134
+ #
135
+ # @example IgnoreScopes: true
136
+ # # good
137
+ # class Blog < ApplicationRecord
138
+ # has_many :posts, -> { order(published_at: :desc) }
139
+ # end
140
+ #
129
141
  # @see https://guides.rubyonrails.org/association_basics.html#bi-directional-associations
130
142
  # @see https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Setting+Inverses
131
143
  class InverseOf < Base
@@ -189,7 +201,7 @@ module RuboCop
189
201
  end
190
202
 
191
203
  def scope?(arguments)
192
- arguments.any?(&:block_type?)
204
+ !ignore_scopes? && arguments.any?(&:block_type?)
193
205
  end
194
206
 
195
207
  def options_requiring_inverse_of?(options)
@@ -236,6 +248,10 @@ module RuboCop
236
248
  SPECIFY_MSG
237
249
  end
238
250
  end
251
+
252
+ def ignore_scopes?
253
+ cop_config['IgnoreScopes'] == true
254
+ end
239
255
  end
240
256
  end
241
257
  end
@@ -37,7 +37,7 @@ module RuboCop
37
37
  class ReadWriteAttribute < Base
38
38
  extend AutoCorrector
39
39
 
40
- MSG = 'Prefer `%<prefer>s` over `%<current>s`.'
40
+ MSG = 'Prefer `%<prefer>s`.'
41
41
  RESTRICT_ON_SEND = %i[read_attribute write_attribute].freeze
42
42
 
43
43
  def_node_matcher :read_write_attribute?, <<~PATTERN
@@ -51,35 +51,51 @@ module RuboCop
51
51
  return unless read_write_attribute?(node)
52
52
  return if within_shadowing_method?(node)
53
53
 
54
- add_offense(node.loc.selector, message: message(node)) do |corrector|
55
- case node.method_name
56
- when :read_attribute
57
- replacement = read_attribute_replacement(node)
58
- when :write_attribute
59
- replacement = write_attribute_replacement(node)
60
- end
61
-
62
- corrector.replace(node.source_range, replacement)
54
+ add_offense(node, message: build_message(node)) do |corrector|
55
+ corrector.replace(node.source_range, node_replacement(node))
63
56
  end
64
57
  end
65
58
 
66
59
  private
67
60
 
68
61
  def within_shadowing_method?(node)
69
- node.each_ancestor(:def).any? do |enclosing_method|
70
- shadowing_method_name = node.first_argument.value.to_s
71
- shadowing_method_name << '=' if node.method?(:write_attribute)
62
+ first_arg = node.first_argument
63
+ return false unless first_arg.respond_to?(:value)
64
+
65
+ enclosing_method = node.each_ancestor(:def).first
66
+ return false unless enclosing_method
72
67
 
73
- enclosing_method.method_name.to_s == shadowing_method_name
68
+ shadowing_method_name = first_arg.value.to_s
69
+ shadowing_method_name << '=' if node.method?(:write_attribute)
70
+ enclosing_method.method?(shadowing_method_name)
71
+ end
72
+
73
+ def build_message(node)
74
+ if node.single_line?
75
+ single_line_message(node)
76
+ else
77
+ multi_line_message(node)
74
78
  end
75
79
  end
76
80
 
77
- def message(node)
81
+ def single_line_message(node)
82
+ format(MSG, prefer: node_replacement(node))
83
+ end
84
+
85
+ def multi_line_message(node)
78
86
  if node.method?(:read_attribute)
79
- format(MSG, prefer: 'self[:attr]', current: 'read_attribute(:attr)')
87
+ format(MSG, prefer: 'self[:attr]')
80
88
  else
81
- format(MSG, prefer: 'self[:attr] = val',
82
- current: 'write_attribute(:attr, val)')
89
+ format(MSG, prefer: 'self[:attr] = val')
90
+ end
91
+ end
92
+
93
+ def node_replacement(node)
94
+ case node.method_name
95
+ when :read_attribute
96
+ read_attribute_replacement(node)
97
+ when :write_attribute
98
+ write_attribute_replacement(node)
83
99
  end
84
100
  end
85
101
 
@@ -8,6 +8,10 @@ module RuboCop
8
8
  # explicitly set to `false`. The presence validator is added
9
9
  # automatically, and explicit presence validation is redundant.
10
10
  #
11
+ # @safety
12
+ # This cop's autocorrection is unsafe because it changes the default error message
13
+ # from "can't be blank" to "must exist".
14
+ #
11
15
  # @example
12
16
  # # bad
13
17
  # belongs_to :user
@@ -46,9 +50,6 @@ module RuboCop
46
50
  # @example source that matches - by association
47
51
  # validates :name, :user, presence: true
48
52
  #
49
- # @example source that matches - with presence options
50
- # validates :user, presence: { message: 'duplicate' }
51
- #
52
53
  # @example source that matches - by a foreign key
53
54
  # validates :user_id, presence: true
54
55
  #
@@ -62,7 +63,7 @@ module RuboCop
62
63
  send nil? :validates
63
64
  (sym $_)+
64
65
  $[
65
- (hash <$(pair (sym :presence) {true hash}) ...>) # presence: true
66
+ (hash <$(pair (sym :presence) true) ...>) # presence: true
66
67
  !(hash <$(pair (sym :strict) {true const}) ...>) # strict: true
67
68
  ]
68
69
  )
@@ -176,6 +176,8 @@ module RuboCop
176
176
  #
177
177
  # @see https://api.rubyonrails.org/classes/ActiveRecord/Migration/CommandRecorder.html
178
178
  class ReversibleMigration < Base
179
+ include MigrationsHelper
180
+
179
181
  MSG = '%<action>s is not reversible.'
180
182
 
181
183
  def_node_matcher :irreversible_schema_statement_call, <<~PATTERN
@@ -207,7 +209,7 @@ module RuboCop
207
209
  PATTERN
208
210
 
209
211
  def on_send(node)
210
- return unless within_change_method?(node)
212
+ return unless in_migration?(node) && within_change_method?(node)
211
213
  return if within_reversible_or_up_only_block?(node)
212
214
 
213
215
  check_irreversible_schema_statement_node(node)
@@ -220,7 +222,7 @@ module RuboCop
220
222
  end
221
223
 
222
224
  def on_block(node)
223
- return unless within_change_method?(node)
225
+ return unless in_migration?(node) && within_change_method?(node)
224
226
  return if within_reversible_or_up_only_block?(node)
225
227
  return if node.body.nil?
226
228
 
@@ -43,19 +43,11 @@ module RuboCop
43
43
  # end
44
44
  # end
45
45
  class ReversibleMigrationMethodDefinition < Base
46
+ include MigrationsHelper
47
+
46
48
  MSG = 'Migrations must contain either a `change` method, or ' \
47
49
  'both an `up` and a `down` method.'
48
50
 
49
- def_node_matcher :migration_class?, <<~PATTERN
50
- (class
51
- (const nil? _)
52
- (send
53
- (const (const {nil? cbase} :ActiveRecord) :Migration)
54
- :[]
55
- (float _))
56
- _)
57
- PATTERN
58
-
59
51
  def_node_matcher :change_method?, <<~PATTERN
60
52
  [ #migration_class? `(def :change (args) _) ]
61
53
  PATTERN
@@ -4,6 +4,7 @@ require_relative 'mixin/active_record_helper'
4
4
  require_relative 'mixin/active_record_migrations_helper'
5
5
  require_relative 'mixin/enforce_superclass'
6
6
  require_relative 'mixin/index_method'
7
+ require_relative 'mixin/migrations_helper'
7
8
  require_relative 'mixin/target_rails_version'
8
9
 
9
10
  require_relative 'rails/action_filter'
@@ -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.13.1'
7
+ STRING = '2.13.2'
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.13.1
4
+ version: 2.13.2
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: 2022-01-09 00:00:00.000000000 Z
13
+ date: 2022-01-15 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -81,6 +81,7 @@ files:
81
81
  - lib/rubocop/cop/mixin/active_record_migrations_helper.rb
82
82
  - lib/rubocop/cop/mixin/enforce_superclass.rb
83
83
  - lib/rubocop/cop/mixin/index_method.rb
84
+ - lib/rubocop/cop/mixin/migrations_helper.rb
84
85
  - lib/rubocop/cop/mixin/target_rails_version.rb
85
86
  - lib/rubocop/cop/rails/action_filter.rb
86
87
  - lib/rubocop/cop/rails/active_record_aliases.rb