Fix bug: Unable to unfollow topics (#19637)

* Fix bug: Unable to unfollow topics

* Rubocop

* Appease audit?
This commit is contained in:
Joshua Wehner 2023-06-29 09:54:10 +02:00 committed by GitHub
parent df82994fba
commit 55b4e74a5a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 24 deletions

View file

@ -75,6 +75,8 @@ class FollowsController < ApplicationController
follow(followable, need_notification: need_notification)
end
clear_followed_tag_caches if followable_klass == Tag
render json: { outcome: @result }
end
@ -108,10 +110,18 @@ class FollowsController < ApplicationController
I18n.t("follows_controller.already_followed")
end
def clear_followed_tag_caches
# Clear the followed_tags model cache, which is nested inside the async_info cache
Rails.cache.delete("#{current_user.cache_key}-#{current_user.last_followed_at&.rfc3339}/followed_tags")
# Clear the async_info cache, which contains the list of tags the user is currently following
Rails.cache.delete("#{current_user.cache_key_with_version}/user-info")
end
def unfollow(followable, followable_type, need_notification: false)
user_follow = current_user.stop_following(followable)
Notification.send_new_follower_notification_without_delay(user_follow, is_read: true) if need_notification
# Clear the user-follows-user cache async
Follows::DeleteCached.call(current_user, followable_type, followable.id)
I18n.t("follows_controller.unfollowed")

View file

@ -1,7 +1,8 @@
import { getInstantClick } from '../topNavigation/utilities';
import { waitOnBaseData } from '../utilities/waitOnBaseData';
import { locale } from '@utilities/locale';
/* global showLoginModal userData showModalAfterError*/
/* global showLoginModal userData showModalAfterError browserStoreCache */
/**
* Sets the text content of the button to the correct 'Follow' state
@ -219,6 +220,7 @@ function handleFollowButtonClick({ target }) {
}
optimisticallyUpdateButtonUI(target);
browserStoreCache('remove');
const { verb } = target.dataset;
@ -409,32 +411,34 @@ function initializeNonUserFollowButtons() {
'.follow-action-button:not(.follow-user):not([data-fetched])',
);
const userLoggedIn =
document.body.getAttribute('data-user-status') === 'logged-in';
waitOnBaseData().then(() => {
const userLoggedIn =
document.body.getAttribute('data-user-status') === 'logged-in';
const user = userLoggedIn ? userData() : null;
const user = userLoggedIn ? userData() : null;
const followedTags = user
? JSON.parse(user.followed_tags).map((tag) => tag.id)
: [];
const followedTags = user
? JSON.parse(user.followed_tags).map((tag) => tag.id)
: [];
const followedTagIds = new Set(followedTags);
const followedTagIds = new Set(followedTags);
nonUserFollowButtons.forEach((button) => {
const { info } = button.dataset;
const buttonInfo = JSON.parse(info);
const { className, name } = buttonInfo;
addAriaLabelToButton({ button, followType: className, followName: name });
if (className === 'Tag' && user) {
// We don't need to make a network request to 'fetch' the status of tag buttons
button.dataset.fetched = true;
const initialButtonFollowState = followedTagIds.has(buttonInfo.id)
? 'true'
: 'false';
updateInitialButtonUI(initialButtonFollowState, button);
} else {
fetchFollowButtonStatus(button, buttonInfo);
}
nonUserFollowButtons.forEach((button) => {
const { info } = button.dataset;
const buttonInfo = JSON.parse(info);
const { className, name } = buttonInfo;
addAriaLabelToButton({ button, followType: className, followName: name });
if (className === 'Tag' && user) {
// We don't need to make a network request to 'fetch' the status of tag buttons
button.dataset.fetched = true;
const initialButtonFollowState = followedTagIds.has(buttonInfo.id)
? 'true'
: 'false';
updateInitialButtonUI(initialButtonFollowState, button);
} else {
fetchFollowButtonStatus(button, buttonInfo);
}
});
});
}

View file

@ -13,12 +13,15 @@ module Follows
def call
return false unless follower
cache_key = "user-#{follower.id}-#{follower.updated_at.rfc3339}/is_following_#{followable_type}_#{followable_id}"
Rails.cache.delete(cache_key)
end
private
attr_accessor :follower, :followable_type, :followable_id
def cache_key
"user-#{follower.id}-#{follower.updated_at.rfc3339}/is_following_#{followable_type}_#{followable_id}"
end
end
end