From a24d110258f3acd19a91d3dc0836d793867dea1d Mon Sep 17 00:00:00 2001 From: Bianca Nenciu Date: Fri, 16 Feb 2024 16:39:18 +0200 Subject: [PATCH] FIX: Preload parent categories for sidebar (#25726) When "lazy load categories" is enabled, only the categories present in the sidebar are preloaded. This is insufficient because the parent categories are necessary too for the sidebar to be rendered properly. --- app/models/site.rb | 11 +++++++- spec/models/site_spec.rb | 34 ++++++++++++++++++++++++ spec/serializers/site_serializer_spec.rb | 18 ++++--------- 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/app/models/site.rb b/app/models/site.rb index c46c666e0b4..1390c1c25a3 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -109,7 +109,16 @@ class Site if @guardian.can_lazy_load_categories? preloaded_category_ids = [] if @guardian.authenticated? - preloaded_category_ids.concat(@guardian.user.secured_sidebar_category_ids(@guardian)) + sidebar_category_ids = @guardian.user.secured_sidebar_category_ids(@guardian) + preloaded_category_ids.concat( + Category + .secured(@guardian) + .select(:parent_category_id) + .distinct + .where(id: sidebar_category_ids) + .pluck(:parent_category_id), + ) + preloaded_category_ids.concat(sidebar_category_ids) end end diff --git a/spec/models/site_spec.rb b/spec/models/site_spec.rb index ff49ad5c5c9..cc23095c014 100644 --- a/spec/models/site_spec.rb +++ b/spec/models/site_spec.rb @@ -183,6 +183,40 @@ RSpec.describe Site do DiscoursePluginRegistry.clear_modifiers! end end + + context "with lazy loaded categories enabled" do + fab!(:user) + + before { SiteSetting.lazy_load_categories_groups = "#{Group::AUTO_GROUPS[:everyone]}" } + + it "does not return any categories for anonymous users" do + site = Site.new(Guardian.new) + + expect(site.categories).to eq([]) + end + + it "returns only sidebar categories and their parent categories" do + parent_category = Fabricate(:category) + category.update!(parent_category: parent_category) + Fabricate(:category_sidebar_section_link, linkable: category, user: user) + + site = Site.new(Guardian.new(user)) + + expect(site.categories.map { |c| c[:id] }).to contain_exactly( + parent_category.id, + category.id, + ) + end + + it "returns only visible sidebar categories" do + Fabricate(:category_sidebar_section_link, linkable: category, user: user) + category.update!(read_restricted: true) + + site = Site.new(Guardian.new(user)) + + expect(site.categories).to eq([]) + end + end end it "omits groups user can not see" do diff --git a/spec/serializers/site_serializer_spec.rb b/spec/serializers/site_serializer_spec.rb index 38019a3a6e8..668c30f3894 100644 --- a/spec/serializers/site_serializer_spec.rb +++ b/spec/serializers/site_serializer_spec.rb @@ -133,32 +133,24 @@ RSpec.describe SiteSerializer do context "with lazy loaded categories enabled" do fab!(:user) - let(:guardian) { Guardian.new(user) } + fab!(:category) + fab!(:sidebar) { Fabricate(:category_sidebar_section_link, linkable: category, user: user) } before { SiteSetting.lazy_load_categories_groups = "#{Group::AUTO_GROUPS[:everyone]}" } - it "categories does not include any categories for anonymous users" do + it "does not include any categories for anonymous users" do serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json expect(serialized[:categories]).to eq(nil) end - it "categories include only sidebar categories" do - Fabricate(:category_sidebar_section_link, linkable: category, user: user) + it "includes preloaded categories for logged in users" do + guardian = Guardian.new(user) serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json expect(serialized[:categories].map { |c| c[:id] }).to contain_exactly(category.id) end - - it "categories include only visible sidebar categories" do - Fabricate(:category_sidebar_section_link, linkable: category, user: user) - category.update!(read_restricted: true) - - serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json - - expect(serialized[:categories]).to eq(nil) - end end describe "#anonymous_default_navigation_menu_tags" do