commit: 682b68438e7b9c1755151777bbb6849c00ca98e4
parent: 09ec6e504be96a8bef72c9d988099191501dde67
Author: alpaca-tc <alpaca-tc@alpaca.tc>
Date: Tue, 16 May 2017 19:06:38 +0900
Improve Account#triadic_closures (#3079)
Diffstat:
2 files changed, 44 insertions(+), 14 deletions(-)
diff --git a/app/models/account.rb b/app/models/account.rb
@@ -259,24 +259,30 @@ class Account < ApplicationRecord
nil
end
- def triadic_closures(account, limit = 5)
+ def triadic_closures(account, limit: 5, offset: 0)
sql = <<-SQL.squish
WITH first_degree AS (
- SELECT target_account_id
- FROM follows
- WHERE account_id = :account_id
- )
+ SELECT target_account_id
+ FROM follows
+ WHERE account_id = :account_id
+ )
SELECT accounts.*
FROM follows
INNER JOIN accounts ON follows.target_account_id = accounts.id
- WHERE account_id IN (SELECT * FROM first_degree) AND target_account_id NOT IN (SELECT * FROM first_degree) AND target_account_id <> :account_id
+ WHERE
+ account_id IN (SELECT * FROM first_degree)
+ AND target_account_id NOT IN (SELECT * FROM first_degree)
+ AND target_account_id NOT IN (:excluded_account_ids)
GROUP BY target_account_id, accounts.id
ORDER BY count(account_id) DESC
+ OFFSET :offset
LIMIT :limit
SQL
+ excluded_account_ids = account.excluded_from_timeline_account_ids + [account.id]
+
find_by_sql(
- [sql, { account_id: account.id, limit: limit }]
+ [sql, { account_id: account.id, excluded_account_ids: excluded_account_ids, limit: limit, offset: offset }]
)
end
diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb
@@ -261,19 +261,43 @@ RSpec.describe Account, type: :model do
end
describe '.triadic_closures' do
- it 'finds accounts you dont follow which are followed by accounts you do follow' do
- me = Fabricate(:account)
- friend = Fabricate(:account)
- friends_friend = Fabricate(:account)
+ subject { described_class.triadic_closures(me) }
+
+ let!(:me) { Fabricate(:account) }
+ let!(:friend) { Fabricate(:account) }
+ let!(:friends_friend) { Fabricate(:account) }
+ let!(:both_follow) { Fabricate(:account) }
+
+ before do
me.follow!(friend)
friend.follow!(friends_friend)
- both_follow = Fabricate(:account)
me.follow!(both_follow)
friend.follow!(both_follow)
+ end
+
+ it 'finds accounts you dont follow which are followed by accounts you do follow' do
+ is_expected.to eq [friends_friend]
+ end
+
+ context 'when you block account' do
+ before do
+ me.block!(friends_friend)
+ end
+
+ it 'rejects blocked accounts' do
+ is_expected.to be_empty
+ end
+ end
- results = Account.triadic_closures(me)
- expect(results).to eq [friends_friend]
+ context 'when you mute account' do
+ before do
+ me.mute!(friends_friend)
+ end
+
+ it 'rejects muted accounts' do
+ is_expected.to be_empty
+ end
end
end