Skip to content

Commit 636e58c

Browse files
committed
Fix cop to detect multiple associations
1 parent 210c368 commit 636e58c

File tree

2 files changed

+31
-10
lines changed

2 files changed

+31
-10
lines changed

lib/rubocop/cop/rails/redundant_presence_validation_on_belongs_to.rb

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class RedundantPresenceValidationOnBelongsTo < Base
3232
extend AutoCorrector
3333
extend TargetRailsVersion
3434

35-
MSG = 'Remove explicit presence validation for `%<association>s`.'
35+
MSG = 'Remove explicit presence validation for %<association>s.'
3636
RESTRICT_ON_SEND = %i[validates].freeze
3737

3838
minimum_target_rails_version 5.0
@@ -43,6 +43,9 @@ class RedundantPresenceValidationOnBelongsTo < Base
4343
# @example source that matches - by association
4444
# validates :user, presence: true
4545
#
46+
# @example source that matches - by association
47+
# validates :name, :user, presence: true
48+
#
4649
# @example source that matches - with presence options
4750
# validates :user, presence: { message: 'duplicate' }
4851
#
@@ -51,8 +54,7 @@ class RedundantPresenceValidationOnBelongsTo < Base
5154
def_node_matcher :presence_validation?, <<~PATTERN
5255
$(
5356
send nil? :validates
54-
(sym $_)
55-
...
57+
(sym $_)+
5658
$(hash <$(pair (sym :presence) {true hash}) ...>)
5759
)
5860
PATTERN
@@ -150,22 +152,27 @@ class RedundantPresenceValidationOnBelongsTo < Base
150152
PATTERN
151153

152154
def on_send(node)
153-
validation, key, options, presence = presence_validation?(node)
155+
validation, all_keys, options, presence = presence_validation?(node)
154156
return unless validation
155157

156-
belongs_to = belongs_to_for(node.parent, key)
157-
return unless belongs_to
158-
return if optional?(belongs_to)
159-
160-
message = format(MSG, association: key.to_s)
158+
keys = all_keys.select do |key|
159+
belongs_to = belongs_to_for(node.parent, key)
160+
belongs_to && !optional?(belongs_to)
161+
end
162+
return if keys.none?
161163

162-
add_offense(presence, message: message) do |corrector|
164+
add_offense(presence, message: message_for(keys)) do |corrector|
163165
remove_presence_validation(corrector, node, options, presence)
164166
end
165167
end
166168

167169
private
168170

171+
def message_for(keys)
172+
display_keys = keys.map { |key| "`#{key}`" }.join('/')
173+
format(MSG, association: display_keys)
174+
end
175+
169176
def belongs_to_for(model_class_node, key)
170177
if key.to_s.end_with?('_id')
171178
normalized_key = key.to_s.delete_suffix('_id').to_sym

spec/rubocop/cop/rails/redundant_presence_validation_on_belongs_to_spec.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,20 @@
101101
RUBY
102102
end
103103

104+
it 'registers an offense for multiple associations' do
105+
expect_offense(<<~RUBY)
106+
belongs_to :user
107+
belongs_to :book
108+
validates :user, :book, presence: true
109+
^^^^^^^^^^^^^^ Remove explicit presence validation for `user`/`book`.
110+
RUBY
111+
112+
expect_correction(<<~RUBY)
113+
belongs_to :user
114+
belongs_to :book
115+
RUBY
116+
end
117+
104118
it 'registers an offense for presence with a message' do
105119
expect_offense(<<~RUBY)
106120
belongs_to :user

0 commit comments

Comments
 (0)