From 199425cee601733ef4f33ec5b76f5afe948cba61 Mon Sep 17 00:00:00 2001 From: Tiago Botelho Date: Wed, 28 Jun 2017 16:05:02 +0100 Subject: [PATCH] Inserts exact matches of username, email and name to the top of the user search list --- app/models/user.rb | 11 +++- .../26125-match-username-on-search.yml | 5 ++ spec/models/user_spec.rb | 65 ++++++++++--------- 3 files changed, 51 insertions(+), 30 deletions(-) create mode 100644 changelogs/unreleased/26125-match-username-on-search.yml diff --git a/app/models/user.rb b/app/models/user.rb index 6dd1b1415d6..35e0d021c47 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -299,11 +299,20 @@ class User < ActiveRecord::Base table = arel_table pattern = "%#{query}%" + order = <<~SQL + CASE + WHEN users.name = %{query} THEN 0 + WHEN users.username = %{query} THEN 1 + WHEN users.email = %{query} THEN 2 + ELSE 3 + END + SQL + where( table[:name].matches(pattern) .or(table[:email].matches(pattern)) .or(table[:username].matches(pattern)) - ) + ).reorder(order % { query: ActiveRecord::Base.connection.quote(query) }, id: :desc) end # searches user by given pattern diff --git a/changelogs/unreleased/26125-match-username-on-search.yml b/changelogs/unreleased/26125-match-username-on-search.yml new file mode 100644 index 00000000000..74e918bec16 --- /dev/null +++ b/changelogs/unreleased/26125-match-username-on-search.yml @@ -0,0 +1,5 @@ +--- +title: Inserts exact matches of name, username and email to the top of the search + list +merge_request: 12525 +author: diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 8e895ec6634..448555d2190 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -754,42 +754,49 @@ describe User, models: true do end describe '.search' do - let(:user) { create(:user) } + let!(:user) { create(:user, name: 'user', username: 'usern', email: 'email@gmail.com') } + let!(:user2) { create(:user, name: 'user name', username: 'username', email: 'someemail@gmail.com') } - it 'returns users with a matching name' do - expect(described_class.search(user.name)).to eq([user]) + describe 'name matching' do + it 'returns users with a matching name with exact match first' do + expect(described_class.search(user.name)).to eq([user, user2]) + end + + it 'returns users with a partially matching name' do + expect(described_class.search(user.name[0..2])).to eq([user2, user]) + end + + it 'returns users with a matching name regardless of the casing' do + expect(described_class.search(user2.name.upcase)).to eq([user2]) + end end - it 'returns users with a partially matching name' do - expect(described_class.search(user.name[0..2])).to eq([user]) + describe 'email matching' do + it 'returns users with a matching Email' do + expect(described_class.search(user.email)).to eq([user, user2]) + end + + it 'returns users with a partially matching Email' do + expect(described_class.search(user.email[0..2])).to eq([user2, user]) + end + + it 'returns users with a matching Email regardless of the casing' do + expect(described_class.search(user2.email.upcase)).to eq([user2]) + end end - it 'returns users with a matching name regardless of the casing' do - expect(described_class.search(user.name.upcase)).to eq([user]) - end + describe 'username matching' do + it 'returns users with a matching username' do + expect(described_class.search(user.username)).to eq([user, user2]) + end - it 'returns users with a matching Email' do - expect(described_class.search(user.email)).to eq([user]) - end + it 'returns users with a partially matching username' do + expect(described_class.search(user.username[0..2])).to eq([user2, user]) + end - it 'returns users with a partially matching Email' do - expect(described_class.search(user.email[0..2])).to eq([user]) - end - - it 'returns users with a matching Email regardless of the casing' do - expect(described_class.search(user.email.upcase)).to eq([user]) - end - - it 'returns users with a matching username' do - expect(described_class.search(user.username)).to eq([user]) - end - - it 'returns users with a partially matching username' do - expect(described_class.search(user.username[0..2])).to eq([user]) - end - - it 'returns users with a matching username regardless of the casing' do - expect(described_class.search(user.username.upcase)).to eq([user]) + it 'returns users with a matching username regardless of the casing' do + expect(described_class.search(user2.username.upcase)).to eq([user2]) + end end end