Skip to content

Commit 5167b41

Browse files
authored
Merge pull request #1028 from koic/fix_an_error_for_rails_unique_validation_without_index
Fix an error for `Rails/UniqueValidationWithoutIndex`
2 parents cf8f9bf + 26dce91 commit 5167b41

File tree

3 files changed

+34
-21
lines changed

3 files changed

+34
-21
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* [#1028](https://github.com/rubocop/rubocop-rails/pull/1028): Fix an error for `Rails/UniqueValidationWithoutIndex` when the `presence: true` option is used alone for the `validates` method. ([@koic][])

lib/rubocop/cop/rails/unique_validation_without_index.rb

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ class UniqueValidationWithoutIndex < Base
3131
RESTRICT_ON_SEND = %i[validates].freeze
3232

3333
def on_send(node)
34-
return if uniqueness_part(node)&.falsey_literal?
35-
return if condition_part?(node)
3634
return unless schema
35+
return unless (uniqueness_part = uniqueness_part(node))
36+
return if uniqueness_part.falsey_literal? || condition_part?(node, uniqueness_part)
3737

38-
klass, table, names = find_schema_information(node)
38+
klass, table, names = find_schema_information(node, uniqueness_part)
3939
return unless names
4040
return if with_index?(klass, table, names)
4141

@@ -44,12 +44,12 @@ def on_send(node)
4444

4545
private
4646

47-
def find_schema_information(node)
47+
def find_schema_information(node, uniqueness_part)
4848
klass = class_node(node)
4949
return unless klass
5050

5151
table = schema.table_by(name: table_name(klass))
52-
names = column_names(node)
52+
names = column_names(node, uniqueness_part)
5353

5454
[klass, table, names]
5555
end
@@ -71,12 +71,12 @@ def include_column_names_in_expression_index?(index, column_names)
7171
end
7272
end
7373

74-
def column_names(node)
74+
def column_names(node, uniqueness_part)
7575
arg = node.first_argument
7676
return unless arg.str_type? || arg.sym_type?
7777

7878
ret = [arg.value]
79-
names_from_scope = column_names_from_scope(node)
79+
names_from_scope = column_names_from_scope(uniqueness_part)
8080
ret.concat(names_from_scope) if names_from_scope
8181

8282
ret = ret.flat_map do |name|
@@ -90,11 +90,10 @@ def column_names(node)
9090
ret.include?(nil) ? nil : ret.to_set
9191
end
9292

93-
def column_names_from_scope(node)
94-
uniq = uniqueness_part(node)
95-
return unless uniq.hash_type?
93+
def column_names_from_scope(uniqueness_part)
94+
return unless uniqueness_part.hash_type?
9695

97-
scope = find_scope(uniq)
96+
scope = find_scope(uniqueness_part)
9897
return unless scope
9998

10099
scope = unfreeze_scope(scope)
@@ -135,14 +134,11 @@ def uniqueness_part(node)
135134
end
136135
end
137136

138-
def condition_part?(node)
139-
pairs = node.arguments.last
140-
return unless pairs.hash_type?
141-
137+
def condition_part?(node, uniqueness_node)
138+
pairs = node.last_argument
139+
return false unless pairs.hash_type?
142140
return true if condition_hash_part?(pairs, keys: %i[if unless])
143-
144-
uniqueness_node = uniqueness_part(node)
145-
return unless uniqueness_node&.hash_type?
141+
return false unless uniqueness_node.hash_type?
146142

147143
condition_hash_part?(uniqueness_node, keys: %i[if unless conditions])
148144
end

spec/rubocop/cop/rails/unique_validation_without_index_spec.rb

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class User < ApplicationRecord
3636
end
3737
RUBY
3838

39-
it 'registers an offense' do
39+
it 'registers an offense when `uniqueness: true`' do
4040
expect_offense(<<~RUBY)
4141
class User
4242
validates :account, uniqueness: true
@@ -45,13 +45,21 @@ class User
4545
RUBY
4646
end
4747

48-
it 'does not register an offense' do
48+
it 'does not register an offense when `uniqueness: false`' do
4949
expect_no_offenses(<<~RUBY)
5050
class User
5151
validates :account, uniqueness: false
5252
end
5353
RUBY
5454
end
55+
56+
it 'does not register an offense when `uniqueness: nil`' do
57+
expect_no_offenses(<<~RUBY)
58+
class User
59+
validates :account, uniqueness: nil
60+
end
61+
RUBY
62+
end
5563
end
5664

5765
context 'when the table has an index but it is not unique' do
@@ -64,14 +72,22 @@ class User
6472
end
6573
RUBY
6674

67-
it 'registers an offense' do
75+
it 'registers an offense when the `uniqueness: true` option is used alone' do
6876
expect_offense(<<~RUBY)
6977
class User
7078
validates :account, uniqueness: true
7179
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Uniqueness validation should have a unique index on the database column.
7280
end
7381
RUBY
7482
end
83+
84+
it 'does not register an offense when the `presence: true` option is used alone' do
85+
expect_no_offenses(<<~RUBY)
86+
class User
87+
validates :account, presence: true
88+
end
89+
RUBY
90+
end
7591
end
7692

7793
context 'with a unique index' do

0 commit comments

Comments
 (0)