From 800aa296953c4a99e16e0493d9260359ef8c8414 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 1 Mar 2016 16:08:48 +0100 Subject: [PATCH] Use ILIKE/LIKE for searching users --- app/models/user.rb | 16 +++++++++++++- spec/models/user_spec.rb | 48 +++++++++++++++++++++++++++++++--------- 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index 505a547d8ec..fc4cf92be60 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -286,8 +286,22 @@ class User < ActiveRecord::Base end end + # Searches users matching the given query. + # + # This method uses ILIKE on PostgreSQL and LIKE on MySQL. + # + # query - The search query as a String + # + # Returns an ActiveRecord::Relation. def search(query) - where("lower(name) LIKE :query OR lower(email) LIKE :query OR lower(username) LIKE :query", query: "%#{query.downcase}%") + table = User.arel_table + pattern = "%#{query}%" + + where( + table[:name].matches(pattern). + or(table[:email].matches(pattern)). + or(table[:username].matches(pattern)) + ) end def by_login(login) diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 412101ac9f9..90207f5153a 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -463,17 +463,43 @@ describe User, models: true do end end - describe 'search' do - let(:user1) { create(:user, username: 'James', email: 'james@testing.com') } - let(:user2) { create(:user, username: 'jameson', email: 'jameson@example.com') } - - it "should be case insensitive" do - expect(User.search(user1.username.upcase).to_a).to eq([user1]) - expect(User.search(user1.username.downcase).to_a).to eq([user1]) - expect(User.search(user2.username.upcase).to_a).to eq([user2]) - expect(User.search(user2.username.downcase).to_a).to eq([user2]) - expect(User.search(user1.username.downcase).to_a.size).to eq(2) - expect(User.search(user2.username.downcase).to_a.size).to eq(1) + describe '.search' do + let(:user) { create(:user) } + + it 'returns users with a matching name' do + expect(described_class.search(user.name)).to eq([user]) + end + + it 'returns users with a partially matching name' do + expect(described_class.search(user.name[0..2])).to eq([user]) + end + + it 'returns users with a matching name regarding of the casing' do + expect(described_class.search(user.name.upcase)).to eq([user]) + 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 Email' do + expect(described_class.search(user.email[0..2])).to eq([user]) + end + + it 'returns users with a matching Email regarding 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 regarding of the casing' do + expect(described_class.search(user.username.upcase)).to eq([user]) end end -- GitLab