diff --git a/app/models/account.rb b/app/models/account.rb index 22b8bce60..b2dfd5eaa 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -89,6 +89,7 @@ class Account < ApplicationRecord include Account::FinderConcern include Account::Header include Account::Interactions + include Account::Mappings include Account::Merging include Account::Search include Account::Sensitizes diff --git a/app/models/concerns/account/interactions.rb b/app/models/concerns/account/interactions.rb index 33d51abed..4eab55ca3 100644 --- a/app/models/concerns/account/interactions.rb +++ b/app/models/concerns/account/interactions.rb @@ -3,74 +3,6 @@ module Account::Interactions extend ActiveSupport::Concern - class_methods do - def following_map(target_account_ids, account_id) - Follow.where(target_account_id: target_account_ids, account_id: account_id).each_with_object({}) do |follow, mapping| - mapping[follow.target_account_id] = { - reblogs: follow.show_reblogs?, - notify: follow.notify?, - languages: follow.languages, - } - end - end - - def followed_by_map(target_account_ids, account_id) - follow_mapping(Follow.where(account_id: target_account_ids, target_account_id: account_id), :account_id) - end - - def blocking_map(target_account_ids, account_id) - follow_mapping(Block.where(target_account_id: target_account_ids, account_id: account_id), :target_account_id) - end - - def blocked_by_map(target_account_ids, account_id) - follow_mapping(Block.where(account_id: target_account_ids, target_account_id: account_id), :account_id) - end - - def muting_map(target_account_ids, account_id) - Mute.where(target_account_id: target_account_ids, account_id: account_id).each_with_object({}) do |mute, mapping| - mapping[mute.target_account_id] = { - notifications: mute.hide_notifications?, - } - end - end - - def requested_map(target_account_ids, account_id) - FollowRequest.where(target_account_id: target_account_ids, account_id: account_id).each_with_object({}) do |follow_request, mapping| - mapping[follow_request.target_account_id] = { - reblogs: follow_request.show_reblogs?, - notify: follow_request.notify?, - languages: follow_request.languages, - } - end - end - - def requested_by_map(target_account_ids, account_id) - follow_mapping(FollowRequest.where(account_id: target_account_ids, target_account_id: account_id), :account_id) - end - - def endorsed_map(target_account_ids, account_id) - follow_mapping(AccountPin.where(account_id: account_id, target_account_id: target_account_ids), :target_account_id) - end - - def account_note_map(target_account_ids, account_id) - AccountNote.where(target_account_id: target_account_ids, account_id: account_id).each_with_object({}) do |note, mapping| - mapping[note.target_account_id] = { - comment: note.comment, - } - end - end - - def domain_blocking_map_by_domain(target_domains, account_id) - follow_mapping(AccountDomainBlock.where(account_id: account_id, domain: target_domains), :domain) - end - - private - - def follow_mapping(query, field) - query.pluck(field).index_with(true) - end - end - included do # Follow relations has_many :follow_requests, dependent: :destroy @@ -290,21 +222,6 @@ module Account::Interactions end end - def relations_map(account_ids, domains = nil, **options) - relations = { - blocked_by: Account.blocked_by_map(account_ids, id), - following: Account.following_map(account_ids, id), - } - - return relations if options[:skip_blocking_and_muting] - - relations.merge!({ - blocking: Account.blocking_map(account_ids, id), - muting: Account.muting_map(account_ids, id), - domain_blocking_by_domain: Account.domain_blocking_map_by_domain(domains, id), - }) - end - def normalized_domain(domain) TagManager.instance.normalize_domain(domain) end diff --git a/app/models/concerns/account/mappings.rb b/app/models/concerns/account/mappings.rb new file mode 100644 index 000000000..c4eddc1fc --- /dev/null +++ b/app/models/concerns/account/mappings.rb @@ -0,0 +1,108 @@ +# frozen_string_literal: true + +module Account::Mappings + extend ActiveSupport::Concern + + class_methods do + def following_map(target_account_ids, account_id) + Follow.where(target_account_id: target_account_ids, account_id: account_id).each_with_object({}) do |follow, mapping| + mapping[follow.target_account_id] = { + reblogs: follow.show_reblogs?, + notify: follow.notify?, + languages: follow.languages, + } + end + end + + def followed_by_map(target_account_ids, account_id) + build_mapping( + Follow.where(account_id: target_account_ids, target_account_id: account_id), + :account_id + ) + end + + def blocking_map(target_account_ids, account_id) + build_mapping( + Block.where(target_account_id: target_account_ids, account_id: account_id), + :target_account_id + ) + end + + def blocked_by_map(target_account_ids, account_id) + build_mapping( + Block.where(account_id: target_account_ids, target_account_id: account_id), + :account_id + ) + end + + def muting_map(target_account_ids, account_id) + Mute.where(target_account_id: target_account_ids, account_id: account_id).each_with_object({}) do |mute, mapping| + mapping[mute.target_account_id] = { + notifications: mute.hide_notifications?, + } + end + end + + def requested_map(target_account_ids, account_id) + FollowRequest.where(target_account_id: target_account_ids, account_id: account_id).each_with_object({}) do |follow_request, mapping| + mapping[follow_request.target_account_id] = { + reblogs: follow_request.show_reblogs?, + notify: follow_request.notify?, + languages: follow_request.languages, + } + end + end + + def requested_by_map(target_account_ids, account_id) + build_mapping( + FollowRequest.where(account_id: target_account_ids, target_account_id: account_id), + :account_id + ) + end + + def endorsed_map(target_account_ids, account_id) + build_mapping( + AccountPin.where(account_id: account_id, target_account_id: target_account_ids), + :target_account_id + ) + end + + def account_note_map(target_account_ids, account_id) + AccountNote.where(target_account_id: target_account_ids, account_id: account_id).each_with_object({}) do |note, mapping| + mapping[note.target_account_id] = { + comment: note.comment, + } + end + end + + def domain_blocking_map_by_domain(target_domains, account_id) + build_mapping( + AccountDomainBlock.where(account_id: account_id, domain: target_domains), + :domain + ) + end + + private + + def build_mapping(query, field) + query + .pluck(field) + .index_with(true) + end + end + + def relations_map(account_ids, domains = nil, **options) + relations = { + blocked_by: Account.blocked_by_map(account_ids, id), + following: Account.following_map(account_ids, id), + } + + return relations if options[:skip_blocking_and_muting] + + relations.merge!({ + blocking: Account.blocking_map(account_ids, id), + muting: Account.muting_map(account_ids, id), + domain_blocking_by_domain: Account.domain_blocking_map_by_domain(domains, id), + }) + end +end diff --git a/spec/models/concerns/account/interactions_spec.rb b/spec/models/concerns/account/interactions_spec.rb index f7ec3a391..e6e9076ed 100644 --- a/spec/models/concerns/account/interactions_spec.rb +++ b/spec/models/concerns/account/interactions_spec.rb @@ -4,94 +4,7 @@ require 'rails_helper' RSpec.describe Account::Interactions do let(:account) { Fabricate(:account) } - let(:account_id) { account.id } - let(:account_ids) { [account_id] } let(:target_account) { Fabricate(:account) } - let(:target_account_id) { target_account.id } - let(:target_account_ids) { [target_account_id] } - - describe '.following_map' do - subject { Account.following_map(target_account_ids, account_id) } - - context 'when Account with Follow' do - it 'returns { target_account_id => true }' do - Fabricate(:follow, account: account, target_account: target_account) - expect(subject).to eq(target_account_id => { reblogs: true, notify: false, languages: nil }) - end - end - - context 'when Account without Follow' do - it 'returns {}' do - expect(subject).to eq({}) - end - end - end - - describe '.followed_by_map' do - subject { Account.followed_by_map(target_account_ids, account_id) } - - context 'when Account with Follow' do - it 'returns { target_account_id => true }' do - Fabricate(:follow, account: target_account, target_account: account) - expect(subject).to eq(target_account_id => true) - end - end - - context 'when Account without Follow' do - it 'returns {}' do - expect(subject).to eq({}) - end - end - end - - describe '.blocking_map' do - subject { Account.blocking_map(target_account_ids, account_id) } - - context 'when Account with Block' do - it 'returns { target_account_id => true }' do - Fabricate(:block, account: account, target_account: target_account) - expect(subject).to eq(target_account_id => true) - end - end - - context 'when Account without Block' do - it 'returns {}' do - expect(subject).to eq({}) - end - end - end - - describe '.muting_map' do - subject { Account.muting_map(target_account_ids, account_id) } - - context 'when Account with Mute' do - before do - Fabricate(:mute, target_account: target_account, account: account, hide_notifications: hide) - end - - context 'when Mute#hide_notifications?' do - let(:hide) { true } - - it 'returns { target_account_id => { notifications: true } }' do - expect(subject).to eq(target_account_id => { notifications: true }) - end - end - - context 'when not Mute#hide_notifications?' do - let(:hide) { false } - - it 'returns { target_account_id => { notifications: false } }' do - expect(subject).to eq(target_account_id => { notifications: false }) - end - end - end - - context 'when Account without Mute' do - it 'returns {}' do - expect(subject).to eq({}) - end - end - end describe '#follow!' do it 'creates and returns Follow' do diff --git a/spec/models/concerns/account/mappings_spec.rb b/spec/models/concerns/account/mappings_spec.rb new file mode 100644 index 000000000..82d711bf2 --- /dev/null +++ b/spec/models/concerns/account/mappings_spec.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Account::Mappings do + let(:account) { Fabricate(:account) } + let(:account_id) { account.id } + let(:account_ids) { [account_id] } + let(:target_account) { Fabricate(:account) } + let(:target_account_id) { target_account.id } + let(:target_account_ids) { [target_account_id] } + + describe '.following_map' do + subject { Account.following_map(target_account_ids, account_id) } + + context 'when Account has a Follow' do + before { Fabricate(:follow, account: account, target_account: target_account) } + + it { is_expected.to eq(target_account_id => { reblogs: true, notify: false, languages: nil }) } + end + + context 'when Account is without Follow' do + it { is_expected.to eq({}) } + end + end + + describe '.followed_by_map' do + subject { Account.followed_by_map(target_account_ids, account_id) } + + context 'when Account has a Follow' do + before { Fabricate(:follow, account: target_account, target_account: account) } + + it { is_expected.to eq(target_account_id => true) } + end + + context 'when Account is without Follow' do + it { is_expected.to eq({}) } + end + end + + describe '.blocking_map' do + subject { Account.blocking_map(target_account_ids, account_id) } + + context 'when Account has a Block' do + before { Fabricate(:block, account: account, target_account: target_account) } + + it { is_expected.to eq(target_account_id => true) } + end + + context 'when Account is without Block' do + it { is_expected.to eq({}) } + end + end + + describe '.muting_map' do + subject { Account.muting_map(target_account_ids, account_id) } + + context 'when Account has a Mute' do + before { Fabricate(:mute, target_account: target_account, account: account, hide_notifications: hide) } + + context 'when Mute#hide_notifications?' do + let(:hide) { true } + + it { is_expected.to eq(target_account_id => { notifications: true }) } + end + + context 'when not Mute#hide_notifications?' do + let(:hide) { false } + + it { is_expected.to eq(target_account_id => { notifications: false }) } + end + end + + context 'when Account without Mute' do + it { is_expected.to eq({}) } + end + end +end