Refactor raw SQL queries to use Arel

This commit is contained in:
Eugen Rochko 2021-03-12 07:00:05 +01:00
parent b5057c4717
commit 19a64c9687
7 changed files with 301 additions and 211 deletions

View file

@ -0,0 +1,101 @@
# frozen_string_literal: true
require 'rails_helper'
describe AccountSearchQueryBuilder do
before do
Fabricate(
:account,
display_name: "Missing",
username: "missing",
domain: "missing.com"
)
end
context 'without account' do
it 'accepts ?, \, : and space as delimiter' do
needle = Fabricate(
:account,
display_name: 'A & l & i & c & e',
username: 'username',
domain: 'example.com'
)
results = described_class.new('A?l\i:c e').build.to_a
expect(results).to eq [needle]
end
it 'finds accounts with matching display_name' do
needle = Fabricate(
:account,
display_name: "Display Name",
username: "username",
domain: "example.com"
)
results = described_class.new("display").build.to_a
expect(results).to eq [needle]
end
it 'finds accounts with matching username' do
needle = Fabricate(
:account,
display_name: "Display Name",
username: "username",
domain: "example.com"
)
results = described_class.new("username").build.to_a
expect(results).to eq [needle]
end
it 'finds accounts with matching domain' do
needle = Fabricate(
:account,
display_name: "Display Name",
username: "username",
domain: "example.com"
)
results = described_class.new("example").build.to_a
expect(results).to eq [needle]
end
it 'limits by 10 by default' do
11.times.each { Fabricate(:account, display_name: "Display Name") }
results = described_class.new("display").build.to_a
expect(results.size).to eq 10
end
it 'accepts arbitrary limits' do
2.times.each { Fabricate(:account, display_name: "Display Name") }
results = described_class.new("display", limit: 1).build.to_a
expect(results.size).to eq 1
end
it 'ranks multiple matches higher' do
needles = [
{ username: "username", display_name: "username" },
{ display_name: "Display Name", username: "username", domain: "example.com" },
].map(&method(:Fabricate).curry(2).call(:account))
results = described_class.new("username").build.to_a
expect(results).to eq needles
end
end
context 'with account' do
let(:account) { Fabricate(:account) }
it 'ranks followed accounts higher' do
needle = Fabricate(:account, username: "Matching")
followed_needle = Fabricate(:account, username: "Matcher")
account.follow!(followed_needle)
results = described_class.new("match", account: account).build.to_a
expect(results).to eq [followed_needle, needle]
expect(results.first.rank).to be > results.last.rank
end
end
end

View file

@ -309,125 +309,6 @@ RSpec.describe Account, type: :model do
end
end
describe '.search_for' do
before do
_missing = Fabricate(
:account,
display_name: "Missing",
username: "missing",
domain: "missing.com"
)
end
it 'accepts ?, \, : and space as delimiter' do
match = Fabricate(
:account,
display_name: 'A & l & i & c & e',
username: 'username',
domain: 'example.com'
)
results = Account.search_for('A?l\i:c e')
expect(results).to eq [match]
end
it 'finds accounts with matching display_name' do
match = Fabricate(
:account,
display_name: "Display Name",
username: "username",
domain: "example.com"
)
results = Account.search_for("display")
expect(results).to eq [match]
end
it 'finds accounts with matching username' do
match = Fabricate(
:account,
display_name: "Display Name",
username: "username",
domain: "example.com"
)
results = Account.search_for("username")
expect(results).to eq [match]
end
it 'finds accounts with matching domain' do
match = Fabricate(
:account,
display_name: "Display Name",
username: "username",
domain: "example.com"
)
results = Account.search_for("example")
expect(results).to eq [match]
end
it 'limits by 10 by default' do
11.times.each { Fabricate(:account, display_name: "Display Name") }
results = Account.search_for("display")
expect(results.size).to eq 10
end
it 'accepts arbitrary limits' do
2.times.each { Fabricate(:account, display_name: "Display Name") }
results = Account.search_for("display", 1)
expect(results.size).to eq 1
end
it 'ranks multiple matches higher' do
matches = [
{ username: "username", display_name: "username" },
{ display_name: "Display Name", username: "username", domain: "example.com" },
].map(&method(:Fabricate).curry(2).call(:account))
results = Account.search_for("username")
expect(results).to eq matches
end
end
describe '.advanced_search_for' do
it 'accepts ?, \, : and space as delimiter' do
account = Fabricate(:account)
match = Fabricate(
:account,
display_name: 'A & l & i & c & e',
username: 'username',
domain: 'example.com'
)
results = Account.advanced_search_for('A?l\i:c e', account)
expect(results).to eq [match]
end
it 'limits by 10 by default' do
11.times { Fabricate(:account, display_name: "Display Name") }
results = Account.search_for("display")
expect(results.size).to eq 10
end
it 'accepts arbitrary limits' do
2.times { Fabricate(:account, display_name: "Display Name") }
results = Account.search_for("display", 1)
expect(results.size).to eq 1
end
it 'ranks followed accounts higher' do
account = Fabricate(:account)
match = Fabricate(:account, username: "Matching")
followed_match = Fabricate(:account, username: "Matcher")
Fabricate(:follow, account: account, target_account: followed_match)
results = Account.advanced_search_for("match", account)
expect(results).to eq [followed_match, match]
expect(results.first.rank).to be > results.last.rank
end
end
describe '#statuses_count' do
subject { Fabricate(:account) }