Improve Account#triadic_closures (#3079)
This commit is contained in:
parent
09ec6e504b
commit
682b68438e
|
@ -259,24 +259,30 @@ class Account < ApplicationRecord
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def triadic_closures(account, limit = 5)
|
def triadic_closures(account, limit: 5, offset: 0)
|
||||||
sql = <<-SQL.squish
|
sql = <<-SQL.squish
|
||||||
WITH first_degree AS (
|
WITH first_degree AS (
|
||||||
SELECT target_account_id
|
SELECT target_account_id
|
||||||
FROM follows
|
FROM follows
|
||||||
WHERE account_id = :account_id
|
WHERE account_id = :account_id
|
||||||
)
|
)
|
||||||
SELECT accounts.*
|
SELECT accounts.*
|
||||||
FROM follows
|
FROM follows
|
||||||
INNER JOIN accounts ON follows.target_account_id = accounts.id
|
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
|
GROUP BY target_account_id, accounts.id
|
||||||
ORDER BY count(account_id) DESC
|
ORDER BY count(account_id) DESC
|
||||||
|
OFFSET :offset
|
||||||
LIMIT :limit
|
LIMIT :limit
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
|
excluded_account_ids = account.excluded_from_timeline_account_ids + [account.id]
|
||||||
|
|
||||||
find_by_sql(
|
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
|
end
|
||||||
|
|
||||||
|
|
|
@ -261,19 +261,43 @@ RSpec.describe Account, type: :model do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '.triadic_closures' do
|
describe '.triadic_closures' do
|
||||||
it 'finds accounts you dont follow which are followed by accounts you do follow' do
|
subject { described_class.triadic_closures(me) }
|
||||||
me = Fabricate(:account)
|
|
||||||
friend = Fabricate(:account)
|
let!(:me) { Fabricate(:account) }
|
||||||
friends_friend = Fabricate(:account)
|
let!(:friend) { Fabricate(:account) }
|
||||||
|
let!(:friends_friend) { Fabricate(:account) }
|
||||||
|
let!(:both_follow) { Fabricate(:account) }
|
||||||
|
|
||||||
|
before do
|
||||||
me.follow!(friend)
|
me.follow!(friend)
|
||||||
friend.follow!(friends_friend)
|
friend.follow!(friends_friend)
|
||||||
|
|
||||||
both_follow = Fabricate(:account)
|
|
||||||
me.follow!(both_follow)
|
me.follow!(both_follow)
|
||||||
friend.follow!(both_follow)
|
friend.follow!(both_follow)
|
||||||
|
end
|
||||||
|
|
||||||
results = Account.triadic_closures(me)
|
it 'finds accounts you dont follow which are followed by accounts you do follow' do
|
||||||
expect(results).to eq [friends_friend]
|
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
|
||||||
|
|
||||||
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Reference in New Issue