Improve Account#triadic_closures (#3079)
This commit is contained in:
		@@ -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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
      results = Account.triadic_closures(me)
 | 
			
		||||
      expect(results).to eq [friends_friend]
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user