Skip to content

Commit

Permalink
Improve have_db_index to better handle columns with multiple indexes (
Browse files Browse the repository at this point in the history
#1542)

The `have_db_index` matcher currently matches on the first index
that has the matching column names. But when used with the `unique`
qualifier that can result in the "wrong" index being matched causing
the test to fail. For example, one unique BTree index, and another
non-unique partial or GIN index.
  • Loading branch information
abrom committed Mar 7, 2023
1 parent bb5ad38 commit 195153c
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 3 deletions.
17 changes: 14 additions & 3 deletions lib/shoulda/matchers/active_record/have_db_index_matcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -197,17 +197,28 @@ def correct_unique?
def matched_index
@_matched_index ||=
if expected_columns.one?
actual_indexes.detect do |index|
sorted_indexes.detect do |index|
Array.wrap(index.columns) == expected_columns
end
else
actual_indexes.detect do |index|
sorted_indexes.detect do |index|
index.columns == expected_columns
end
end
end

def actual_indexes
def sorted_indexes
if qualifiers.include?(:unique)
# return indexes with unique matching the qualifier first
unsorted_indexes.sort_by do |index|
index.unique == qualifiers[:unique] ? 0 : 1
end
else
unsorted_indexes
end
end

def unsorted_indexes
model.connection.indexes(table_name)
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,36 @@
unique: true,
qualifier_args: [],
)

context 'when there are multiple possible matching columns' do
let(:model) do
define_model(
'Employee',
{ ssn: :string },
parent_class: DevelopmentRecord,
customize_table: -> (table) {
table.index(:ssn, name: 'aaa', unique: false)
table.index(:ssn, name: 'bbb', unique: true)
table.index(:ssn, name: 'ccc', unique: false)
},
)
end

it 'matches in the positive' do
expect(model.new).to have_db_index(:ssn).unique
end

it 'does not match in the negative' do
assertion = lambda do
expect(model.new).not_to have_db_index(:ssn).unique
end

expect(&assertion).to fail_with_message(<<-MESSAGE)
Expected the employees table not to have a unique index on :ssn, but it
does.
MESSAGE
end
end
end

context 'when qualified with unique: true' do
Expand Down

0 comments on commit 195153c

Please sign in to comment.