From 76db815e9c46db07c4a1d2ecc75ded7a482a4685 Mon Sep 17 00:00:00 2001 From: Mahad Kalam Date: Tue, 4 Aug 2026 18:26:45 +0000 Subject: [PATCH 1/2] Search display name overrides in user fuzzy search Amp-Thread-ID: https://ampcode.com/threads/T-019fcdfd-772e-7020-8857-adbfd52bbc72 --- app/models/concerns/user_fuzzy_search.rb | 5 +++++ test/models/concerns/user_fuzzy_search_test.rb | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/app/models/concerns/user_fuzzy_search.rb b/app/models/concerns/user_fuzzy_search.rb index 534da37f0..abd091b2a 100644 --- a/app/models/concerns/user_fuzzy_search.rb +++ b/app/models/concerns/user_fuzzy_search.rb @@ -18,6 +18,7 @@ def fuzzy_ranked_search(term, limit: 20) candidate_parts = [ "SELECT id FROM users WHERE slack_uid = :exact", "SELECT id FROM users WHERE username ILIKE :contains", + "SELECT id FROM users WHERE display_name_override ILIKE :contains", "SELECT id FROM users WHERE github_username ILIKE :contains", "SELECT id FROM users WHERE slack_username ILIKE :contains", "SELECT user_id AS id FROM email_addresses WHERE email ILIKE :contains" @@ -33,6 +34,10 @@ def fuzzy_ranked_search(term, limit: 20) WHEN users.username ILIKE :prefix THEN 50 WHEN users.username ILIKE :contains THEN 10 ELSE 0 END + + CASE WHEN users.display_name_override ILIKE :ilike_exact THEN 100 + WHEN users.display_name_override ILIKE :prefix THEN 50 + WHEN users.display_name_override ILIKE :contains THEN 10 + ELSE 0 END + CASE WHEN users.github_username ILIKE :ilike_exact THEN 100 WHEN users.github_username ILIKE :prefix THEN 50 WHEN users.github_username ILIKE :contains THEN 10 diff --git a/test/models/concerns/user_fuzzy_search_test.rb b/test/models/concerns/user_fuzzy_search_test.rb index 523c219d1..ff89ff0cd 100644 --- a/test/models/concerns/user_fuzzy_search_test.rb +++ b/test/models/concerns/user_fuzzy_search_test.rb @@ -13,6 +13,7 @@ # - rank scoring tiers (id/slack_uid exact = 1000; field exact = 100; # prefix = 50; contains = 10; tiers compound additively) # - case-insensitive ILIKE on username/email fields +# - display name overrides are searchable and ranked like other name fields # - case-sensitive equality on slack_uid # - matched_email picks best email (exact > prefix > contains > any) # - matched_email is nil only when the user has zero emails @@ -114,6 +115,16 @@ def with_email(user, email) assert User.fuzzy_ranked_search("MIXEDCASEUSER").any? { |r| r.id == u.id } end + test "display name override is searchable and ranked case-insensitively" do + u = create_user(username: "unrelated_username", display_name_override: "Custom Display Name") + + exact = User.fuzzy_ranked_search("custom display name").find { |r| r.id == u.id } + substring = User.fuzzy_ranked_search("DISPLAY").find { |r| r.id == u.id } + + assert_operator exact.rank_score, :>=, 100 + assert_operator substring.rank_score, :>=, 10 + end + # ----- multi-field tiers ----- test "github_username, slack_username, and email tiers contribute" do From 8ab524505b9823888da399032ad8933573a49c9c Mon Sep 17 00:00:00 2001 From: Mahad Kalam Date: Tue, 4 Aug 2026 18:50:52 +0000 Subject: [PATCH 2/2] Index display name overrides for fuzzy search Amp-Thread-ID: https://ampcode.com/threads/T-019fcdfd-772e-7020-8857-adbfd52bbc72 --- ...gm_index_to_users_display_name_override.rb | 21 +++++++++++++++++++ db/schema.rb | 3 ++- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20260804184518_add_trgm_index_to_users_display_name_override.rb diff --git a/db/migrate/20260804184518_add_trgm_index_to_users_display_name_override.rb b/db/migrate/20260804184518_add_trgm_index_to_users_display_name_override.rb new file mode 100644 index 000000000..37e1d4334 --- /dev/null +++ b/db/migrate/20260804184518_add_trgm_index_to_users_display_name_override.rb @@ -0,0 +1,21 @@ +class AddTrgmIndexToUsersDisplayNameOverride < ActiveRecord::Migration[8.1] + disable_ddl_transaction! + + def up + enable_extension :pg_trgm unless extension_enabled?(:pg_trgm) + + add_index :users, :display_name_override, + name: :index_users_on_display_name_override_trgm, + using: :gin, + opclass: :gin_trgm_ops, + algorithm: :concurrently, + if_not_exists: true + end + + def down + remove_index :users, :display_name_override, + name: :index_users_on_display_name_override_trgm, + algorithm: :concurrently, + if_exists: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 558fc04f0..b00e5b5bc 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.1].define(version: 2026_07_30_191404) do +ActiveRecord::Schema[8.1].define(version: 2026_08_04_184518) do # These are extensions that must be enabled in order to support this database enable_extension "pg_catalog.plpgsql" enable_extension "pg_stat_statements" @@ -711,6 +711,7 @@ t.string "username" t.boolean "uses_slack_status", default: false, null: false t.boolean "weekly_summary_email_enabled", default: true, null: false + t.index ["display_name_override"], name: "index_users_on_display_name_override_trgm", opclass: :gin_trgm_ops, using: :gin t.index ["github_uid", "github_access_token"], name: "index_users_on_github_uid_and_access_token" t.index ["github_uid"], name: "index_users_on_github_uid" t.index ["github_username"], name: "index_users_on_github_username_trgm", opclass: :gin_trgm_ops, using: :gin