From d43d8e0023f9c2c7e0265e5f1a5879acb3b98825 Mon Sep 17 00:00:00 2001 From: Natalie Tay Date: Tue, 17 Dec 2024 08:06:19 +0800 Subject: [PATCH] FIX: Searchable user fields do not always have an integer name (#30223) --- app/models/user_custom_field.rb | 5 +++- spec/models/user_custom_field_spec.rb | 39 +++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 spec/models/user_custom_field_spec.rb diff --git a/app/models/user_custom_field.rb b/app/models/user_custom_field.rb index e4d9b4f9182..7c0abdf066d 100644 --- a/app/models/user_custom_field.rb +++ b/app/models/user_custom_field.rb @@ -8,7 +8,10 @@ class UserCustomField < ActiveRecord::Base scope :searchable, -> do joins( - "INNER JOIN user_fields ON user_fields.id = REPLACE(user_custom_fields.name, 'user_field_', '')::INTEGER AND user_fields.searchable IS TRUE AND user_custom_fields.name like 'user_field_%'", + "INNER JOIN user_fields ON user_fields.id = REPLACE(user_custom_fields.name, 'user_field_', '')::INTEGER", + ).where("user_fields.searchable = TRUE").where( + "user_custom_fields.name ~ ?", + '^user_field_\\d+$', ) end end diff --git a/spec/models/user_custom_field_spec.rb b/spec/models/user_custom_field_spec.rb new file mode 100644 index 00000000000..65a889b65a0 --- /dev/null +++ b/spec/models/user_custom_field_spec.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +RSpec.describe UserCustomField do + describe ".searchable" do + it "includes user_custom_fields with valid, searchable user_field references" do + Fabricate(:user_field, id: 123, searchable: true) + valid_user_custom_field = Fabricate(:user_custom_field, name: "user_field_123") + + result = UserCustomField.searchable + + expect(result).to include(valid_user_custom_field) + end + + it "excludes user_custom_fields with non-searchable user_field references" do + Fabricate(:user_field, id: 456, searchable: false) + non_searchable_custom_field = Fabricate(:user_custom_field, name: "user_field_456") + + result = UserCustomField.searchable + + expect(result).not_to include(non_searchable_custom_field) + end + + it "excludes user_custom_fields with invalid user_field references" do + invalid_user_custom_field = Fabricate(:user_custom_field, name: "user_field_invalid") + + result = UserCustomField.searchable + + expect(result).not_to include(invalid_user_custom_field) + end + + it "excludes user_custom_fields with unrelated names" do + unrelated_custom_field = Fabricate(:user_custom_field, name: "cost_center") + + result = UserCustomField.searchable + + expect(result).not_to include(unrelated_custom_field) + end + end +end