From c17c07158a7b7979e2dc986ce546993c5ed03d34 Mon Sep 17 00:00:00 2001 From: David Yip Date: Sat, 27 Jan 2018 01:23:14 -0600 Subject: [PATCH] Introduce Glitch::AccountRelationships (#193) Where possible, it is a good idea to add new backend code in ways that will minimize conflict with upstream changes. We can't do that everywhere, but we can move our custom methods to a module that won't be modified upstream, and that's a start. This commit also gets the block/mute note maps into REST::RelationshipSerializer under the "block_notes" and "mute_notes" keys. --- app/models/account.rb | 1 + .../concerns/glitch/account_interactions.rb | 25 ++++++ .../account_relationships_presenter.rb | 5 +- .../rest/relationship_serializer.rb | 11 ++- .../glitch/account_interactions_spec.rb | 78 +++++++++++++++++++ 5 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 app/models/concerns/glitch/account_interactions.rb create mode 100644 spec/models/concerns/glitch/account_interactions_spec.rb diff --git a/app/models/account.rb b/app/models/account.rb index 1abd49b1e4..0d47495874 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -52,6 +52,7 @@ class Account < ApplicationRecord include AccountFinderConcern include AccountHeader include AccountInteractions + include Glitch::AccountInteractions include Attachmentable include Remotable include Paginable diff --git a/app/models/concerns/glitch/account_interactions.rb b/app/models/concerns/glitch/account_interactions.rb new file mode 100644 index 0000000000..e3a5f21ab7 --- /dev/null +++ b/app/models/concerns/glitch/account_interactions.rb @@ -0,0 +1,25 @@ +# frozen_string_literals: true + +module Glitch::AccountInteractions + extend ActiveSupport::Concern + + class_methods do + def mute_note_map(target_account_ids, account_id) + notes_from_relationship(Mute, target_account_ids, account_id).each_with_object({}) do |mute, mapping| + mapping[mute.target_account_id] = mute.note&.text + end + end + + def block_note_map(target_account_ids, account_id) + notes_from_relationship(Block, target_account_ids, account_id).each_with_object({}) do |block, mapping| + mapping[block.target_account_id] = block.note&.text + end + end + + private + + def notes_from_relationship(klass, target_account_ids, account_id) + klass.where(target_account_id: target_account_ids, account_id: account_id).includes(:note) + end + end +end diff --git a/app/presenters/account_relationships_presenter.rb b/app/presenters/account_relationships_presenter.rb index bf1ba37161..8958410d61 100644 --- a/app/presenters/account_relationships_presenter.rb +++ b/app/presenters/account_relationships_presenter.rb @@ -2,7 +2,8 @@ class AccountRelationshipsPresenter attr_reader :following, :followed_by, :blocking, - :muting, :requested, :domain_blocking + :muting, :requested, :domain_blocking, + :mute_notes, :block_notes def initialize(account_ids, current_account_id, **options) @following = Account.following_map(account_ids, current_account_id).merge(options[:following_map] || {}) @@ -11,5 +12,7 @@ class AccountRelationshipsPresenter @muting = Account.muting_map(account_ids, current_account_id).merge(options[:muting_map] || {}) @requested = Account.requested_map(account_ids, current_account_id).merge(options[:requested_map] || {}) @domain_blocking = Account.domain_blocking_map(account_ids, current_account_id).merge(options[:domain_blocking_map] || {}) + @mute_notes = Account.mute_note_map(account_ids, current_account_id).merge(options[:mute_note_map] || {}) + @block_notes = Account.block_note_map(account_ids, current_account_id).merge(options[:block_note_map] || {}) end end diff --git a/app/serializers/rest/relationship_serializer.rb b/app/serializers/rest/relationship_serializer.rb index 45bfd4d6e7..0cbf25d2e8 100644 --- a/app/serializers/rest/relationship_serializer.rb +++ b/app/serializers/rest/relationship_serializer.rb @@ -2,7 +2,8 @@ class REST::RelationshipSerializer < ActiveModel::Serializer attributes :id, :following, :showing_reblogs, :followed_by, :blocking, - :muting, :muting_notifications, :requested, :domain_blocking + :muting, :muting_notifications, :requested, :domain_blocking, + :mute_notes, :block_notes def id object.id.to_s @@ -34,6 +35,14 @@ class REST::RelationshipSerializer < ActiveModel::Serializer (instance_options[:relationships].muting[object.id] || {})[:notifications] || false end + def mute_notes + instance_options[:relationships].mute_notes[object.id] || '' + end + + def block_notes + instance_options[:relationships].block_notes[object.id] || '' + end + def requested instance_options[:relationships].requested[object.id] ? true : false end diff --git a/spec/models/concerns/glitch/account_interactions_spec.rb b/spec/models/concerns/glitch/account_interactions_spec.rb new file mode 100644 index 0000000000..86e73b306f --- /dev/null +++ b/spec/models/concerns/glitch/account_interactions_spec.rb @@ -0,0 +1,78 @@ +require 'rails_helper' + +describe Glitch::AccountInteractions do + let(:account) { Fabricate(:account, username: 'account') } + let(:account_id) { account.id } + let(:account_ids) { [account_id] } + let(:target_account) { Fabricate(:account, username: 'target') } + let(:target_account_id) { target_account.id } + let(:target_account_ids) { [target_account_id] } + + describe '.mute_note_map' do + subject { Account.mute_note_map(target_account_ids, account_id) } + + context 'account with Mute' do + before do + Fabricate(:mute, target_account: target_account, account: account).tap do |m| + m.create_note!(note: note) if note + end + end + + context 'with a note' do + let(:note) { 'Too many jorts' } + + it 'returns { target_account_id => "(a note)" }' do + is_expected.to eq(target_account_id => 'Too many jorts') + end + end + + context 'with no associated note' do + let(:note) { nil } + + it 'returns { target_account_id => nil }' do + is_expected.to eq(target_account_id => nil) + end + end + end + + context 'account without Mute' do + it 'returns {}' do + is_expected.to eq({}) + end + end + end + + describe '.block_note_map' do + subject { Account.block_note_map(target_account_ids, account_id) } + + context 'account with Block' do + before do + Fabricate(:block, target_account: target_account, account: account).tap do |m| + m.create_note!(note: note) if note + end + end + + context 'with a note' do + let(:note) { 'Too many oats' } + + it 'returns { target_account_id => "(a note)" }' do + is_expected.to eq(target_account_id => 'Too many oats') + end + end + + context 'with no associated note' do + let(:note) { nil } + + it 'returns { target_account_id => nil }' do + is_expected.to eq(target_account_id => nil) + end + end + end + + context 'account without Block' do + it 'returns {}' do + is_expected.to eq({}) + end + end + end +end