about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatt Jankowski <mjankowski@thoughtbot.com>2017-04-09 08:45:01 -0400
committerEugen <eugen@zeonfederated.com>2017-04-09 14:45:01 +0200
commit388ec0d5b6d1549abed15802d6bdbfc8b1c05294 (patch)
tree218a713f7bd177f964f44a4c3fe0092bddfc5382
parent71706f21c28f5ae623ee69810fe26a34fb79b446 (diff)
Search cleanup (#1333)
* Clean up SQL output in Tag and Account search methods

* Add basic coverage for Tag.search_for

* Add coverage for Account.search_for

* Add coverage for Account.advanced_search_for
-rw-r--r--app/models/account.rb12
-rw-r--r--app/models/tag.rb4
-rw-r--r--spec/models/account_spec.rb55
-rw-r--r--spec/models/tag_spec.rb11
4 files changed, 74 insertions, 8 deletions
diff --git a/app/models/account.rb b/app/models/account.rb
index cbba8b5b6..c59c76009 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -203,7 +203,7 @@ class Account < ApplicationRecord
     end
 
     def triadic_closures(account, limit = 5)
-      sql = <<SQL
+      sql = <<-SQL.squish
         WITH first_degree AS (
             SELECT target_account_id
             FROM follows
@@ -216,7 +216,7 @@ class Account < ApplicationRecord
         GROUP BY target_account_id, accounts.id
         ORDER BY count(account_id) DESC
         LIMIT ?
-SQL
+      SQL
 
       Account.find_by_sql([sql, account.id, account.id, limit])
     end
@@ -226,7 +226,7 @@ SQL
       textsearch = '(setweight(to_tsvector(\'simple\', accounts.display_name), \'A\') || setweight(to_tsvector(\'simple\', accounts.username), \'B\') || setweight(to_tsvector(\'simple\', coalesce(accounts.domain, \'\')), \'C\'))'
       query      = 'to_tsquery(\'simple\', \'\'\' \' || ' + terms + ' || \' \'\'\' || \':*\')'
 
-      sql = <<SQL
+      sql = <<-SQL.squish
         SELECT
           accounts.*,
           ts_rank_cd(#{textsearch}, #{query}, 32) AS rank
@@ -234,7 +234,7 @@ SQL
         WHERE #{query} @@ #{textsearch}
         ORDER BY rank DESC
         LIMIT ?
-SQL
+      SQL
 
       Account.find_by_sql([sql, limit])
     end
@@ -244,7 +244,7 @@ SQL
       textsearch = '(setweight(to_tsvector(\'simple\', accounts.display_name), \'A\') || setweight(to_tsvector(\'simple\', accounts.username), \'B\') || setweight(to_tsvector(\'simple\', coalesce(accounts.domain, \'\')), \'C\'))'
       query      = 'to_tsquery(\'simple\', \'\'\' \' || ' + terms + ' || \' \'\'\' || \':*\')'
 
-      sql = <<SQL
+      sql = <<-SQL.squish
         SELECT
           accounts.*,
           (count(f.id) + 1) * ts_rank_cd(#{textsearch}, #{query}, 32) AS rank
@@ -254,7 +254,7 @@ SQL
         GROUP BY accounts.id
         ORDER BY rank DESC
         LIMIT ?
-SQL
+      SQL
 
       Account.find_by_sql([sql, account.id, account.id, limit])
     end
diff --git a/app/models/tag.rb b/app/models/tag.rb
index 15625ca43..6209d7dab 100644
--- a/app/models/tag.rb
+++ b/app/models/tag.rb
@@ -17,7 +17,7 @@ class Tag < ApplicationRecord
       textsearch = 'to_tsvector(\'simple\', tags.name)'
       query      = 'to_tsquery(\'simple\', \'\'\' \' || ' + terms + ' || \' \'\'\' || \':*\')'
 
-      sql = <<SQL
+      sql = <<-SQL.squish
         SELECT
           tags.*,
           ts_rank_cd(#{textsearch}, #{query}) AS rank
@@ -25,7 +25,7 @@ class Tag < ApplicationRecord
         WHERE #{query} @@ #{textsearch}
         ORDER BY rank DESC
         LIMIT ?
-SQL
+      SQL
 
       Tag.find_by_sql([sql, limit])
     end
diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb
index 93a45459d..0c3b2b042 100644
--- a/spec/models/account_spec.rb
+++ b/spec/models/account_spec.rb
@@ -170,6 +170,61 @@ RSpec.describe Account, type: :model do
     end
   end
 
+  describe '.search_for' do
+    before do
+      @match = Fabricate(
+        :account,
+        display_name: "Display Name",
+        username: "username",
+        domain: "example.com"
+      )
+      _missing = Fabricate(
+        :account,
+        display_name: "Missing",
+        username: "missing",
+        domain: "missing.com"
+      )
+    end
+
+    it 'finds accounts with matching display_name' do
+      results = Account.search_for("display")
+      expect(results).to eq [@match]
+    end
+
+    it 'finds accounts with matching username' do
+      results = Account.search_for("username")
+      expect(results).to eq [@match]
+    end
+
+    it 'finds accounts with matching domain' do
+      results = Account.search_for("example")
+      expect(results).to eq [@match]
+    end
+
+    it 'ranks multiple matches higher' do
+      account = Fabricate(
+        :account,
+        username: "username",
+        display_name: "username"
+      )
+      results = Account.search_for("username")
+      expect(results).to eq [account, @match]
+    end
+  end
+
+  describe '.advanced_search_for' do
+    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 '.find_local' do
     before do
       Fabricate(:account, username: 'Alice')
diff --git a/spec/models/tag_spec.rb b/spec/models/tag_spec.rb
index 360bbc16d..7a5b8ec89 100644
--- a/spec/models/tag_spec.rb
+++ b/spec/models/tag_spec.rb
@@ -12,4 +12,15 @@ RSpec.describe Tag, type: :model do
       expect(subject.match('https://en.wikipedia.org/wiki/Ghostbusters_(song)#Lawsuit')).to be_nil
     end
   end
+
+  describe '.search_for' do
+    it 'finds tag records with matching names' do
+      tag = Fabricate(:tag, name: "match")
+      _miss_tag = Fabricate(:tag, name: "miss")
+
+      results = Tag.search_for("match")
+
+      expect(results).to eq [tag]
+    end
+  end
 end