diff --git a/app/models/category_list.rb b/app/models/category_list.rb index 90ca8e2a7f3..2ed506273a3 100644 --- a/app/models/category_list.rb +++ b/app/models/category_list.rb @@ -62,7 +62,7 @@ class CategoryList category_featured_topics = CategoryFeaturedTopic.select([:category_id, :topic_id]).order(:rank) - @all_topics = Topic.where(id: category_featured_topics.map(&:topic_id)) + @all_topics = Topic.where(id: category_featured_topics.map(&:topic_id)).includes(:shared_draft, :category) if @guardian.authenticated? @all_topics = @all_topics diff --git a/spec/requests/categories_controller_spec.rb b/spec/requests/categories_controller_spec.rb index 7a539a4af01..fdaf5802e65 100644 --- a/spec/requests/categories_controller_spec.rb +++ b/spec/requests/categories_controller_spec.rb @@ -159,6 +159,42 @@ describe CategoriesController do expect(category_response["subcategory_list"][0]["id"]).to eq(subcategory.id) end + it "does not n+1 with multiple topics" do + category1 = Fabricate(:category) + category2 = Fabricate(:category) + topic1 = Fabricate(:topic, category: category1) + + CategoryFeaturedTopic.feature_topics + SiteSetting.desktop_category_page_style = "categories_with_featured_topics" + + # warmup + get "/categories.json" + expect(response.status).to eq(200) + + first_request_queries = track_sql_queries do + get "/categories.json" + expect(response.status).to eq(200) + end + + category_response = response.parsed_body["category_list"]["categories"].find { |c| c["id"] == category1.id } + expect(category_response["topics"].count).to eq(1) + + topic2 = Fabricate(:topic, category: category2) + CategoryFeaturedTopic.feature_topics + + second_request_queries = track_sql_queries do + get "/categories.json" + expect(response.status).to eq(200) + end + + category1_response = response.parsed_body["category_list"]["categories"].find { |c| c["id"] == category1.id } + category2_response = response.parsed_body["category_list"]["categories"].find { |c| c["id"] == category2.id } + expect(category1_response["topics"].size).to eq(1) + expect(category2_response["topics"].size).to eq(1) + + expect(first_request_queries.count).to eq(second_request_queries.count) + end + it 'does not show uncategorized unless allow_uncategorized_topics' do SiteSetting.desktop_category_page_style = "categories_boxes_with_topics" diff --git a/spec/support/helpers.rb b/spec/support/helpers.rb index 21a91ca0cae..c92b928185d 100644 --- a/spec/support/helpers.rb +++ b/spec/support/helpers.rb @@ -181,4 +181,17 @@ module Helpers target.send(:remove_const, const) target.const_set(const, old) end + + def track_sql_queries + queries = [] + callback = ->(*, payload) { + queries << payload.fetch(:sql) unless ["CACHE", "SCHEMA"].include?(payload.fetch(:name)) + } + + ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do + yield + end + + queries + end end