FIX: Order categories in SQL for Categories#search (#26810)

Otherwise, the results don't make sense if the number of categories is
more than the limit provided.
This commit is contained in:
Daniel Waterworth 2024-05-01 12:21:10 -05:00 committed by GitHub
parent c1f6ec5f62
commit b2fe8510e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 19 additions and 13 deletions

View File

@ -412,6 +412,13 @@ class CategoriesController < ApplicationController
)
.joins("LEFT JOIN topics t on t.id = categories.topic_id")
.select("categories.*, t.slug topic_slug")
.order(
"starts_with(lower(categories.name), #{ActiveRecord::Base.connection.quote(term)}) DESC",
"categories.parent_category_id IS NULL DESC",
"categories.id IS NOT DISTINCT FROM #{ActiveRecord::Base.connection.quote(prioritized_category_id)} DESC",
"categories.parent_category_id IS NOT DISTINCT FROM #{ActiveRecord::Base.connection.quote(prioritized_category_id)} DESC",
"categories.id ASC",
)
.limit(limit)
.offset((page - 1) * limit)
@ -421,19 +428,6 @@ class CategoriesController < ApplicationController
Category.preload_user_fields!(guardian, categories)
# Prioritize categories that start with the term, then top-level
# categories, then subcategories
categories =
categories.to_a.sort_by do |category|
[
category.name.downcase.starts_with?(term) ? 0 : 1,
category.parent_category_id.blank? ? 0 : 1,
category.id == prioritized_category_id ? 0 : 1,
category.parent_category_id == prioritized_category_id ? 0 : 1,
category.id,
]
end
response = {
categories_count: categories_count,
categories: serialize_data(categories, SiteCategorySerializer, scope: guardian),

View File

@ -1408,6 +1408,18 @@ RSpec.describe CategoriesController do
[category4.id, category2.id, category3.id, category1.id],
)
end
it "returns categories in the correct order when the limit is lower than the total number of categories" do
categories =
4.times.flat_map do |i|
get "/categories/search.json", params: { term: "ordered", page: i + 1, limit: 1 }
response.parsed_body["categories"]
end
expect(categories.map { |c| c["id"] }).to eq(
[category4.id, category2.id, category3.id, category1.id],
)
end
end
it "returns user fields" do