diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 075c6b60e3e..af1ae82f7a2 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -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), diff --git a/spec/requests/categories_controller_spec.rb b/spec/requests/categories_controller_spec.rb index 735330957cc..6d7ac724541 100644 --- a/spec/requests/categories_controller_spec.rb +++ b/spec/requests/categories_controller_spec.rb @@ -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