diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index bada2b9bd7c..c85b3d6742e 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -394,6 +394,16 @@ 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, + ] + end + if include_ancestors ancestors = Category.secured(guardian).ancestors_of(categories.map(&:id)) diff --git a/spec/requests/categories_controller_spec.rb b/spec/requests/categories_controller_spec.rb index 52d3091effa..0b8fdf4c3a6 100644 --- a/spec/requests/categories_controller_spec.rb +++ b/spec/requests/categories_controller_spec.rb @@ -1274,6 +1274,27 @@ RSpec.describe CategoriesController do end end + context "with order" do + fab!(:category1) { Fabricate(:category, name: "Category Ordered", parent_category: category) } + fab!(:category2) { Fabricate(:category, name: "Ordered Category", parent_category: category) } + fab!(:category3) { Fabricate(:category, name: "Category Ordered") } + fab!(:category4) { Fabricate(:category, name: "Ordered Category") } + + before do + [category1, category2, category3, category4].each do |c| + SearchIndexer.index(c, force: true) + end + end + + it "returns in correct order" do + get "/categories/search.json", params: { term: "ordered" } + + expect(response.parsed_body["categories"].map { |c| c["id"] }).to eq( + [category4.id, category2.id, category3.id, category1.id], + ) + end + end + it "returns user fields" do sign_in(admin)