diff --git a/app/models/card/searchable.rb b/app/models/card/searchable.rb index 8cc108b23..205564864 100644 --- a/app/models/card/searchable.rb +++ b/app/models/card/searchable.rb @@ -10,6 +10,23 @@ module Card::Searchable end end + class_methods do + def mentioning_all(terms, user:) + query = combined_terms_fts_query(terms) + mentioning(query, user: user) + end + + private + + def combined_terms_fts_query(terms) + terms.map { |term| sanitize_fts_term(term) }.join(' AND ') + end + + def sanitize_fts_term(term) + term.gsub('"', '""').then { |t| "\"#{t}\"*" } + end + end + def search_title title end diff --git a/app/models/filter.rb b/app/models/filter.rb index 9bfefe176..7aa224f21 100644 --- a/app/models/filter.rb +++ b/app/models/filter.rb @@ -32,10 +32,7 @@ def cards result = result.where(cards: { created_at: creation_window }) if creation_window result = result.closed_at_window(closure_window) if closure_window result = result.closed_by(closers) if closers.present? - result = terms.reduce(result) do |result, term| - result.mentioning(term, user: creator) - end - + result = result.mentioning_all(terms, user: creator) if terms.present? result.distinct end end diff --git a/test/controllers/cards_controller_test.rb b/test/controllers/cards_controller_test.rb index c6c56fc83..edc4690f2 100644 --- a/test/controllers/cards_controller_test.rb +++ b/test/controllers/cards_controller_test.rb @@ -10,8 +10,13 @@ class CardsControllerTest < ActionDispatch::IntegrationTest assert_response :success end - test "filtered index" do - get cards_path(filters(:jz_assignments).as_params.merge(term: "haggis")) + test "filtered index with single term" do + get cards_path(filters(:jz_assignments).as_params.merge(terms: ["haggis"])) + assert_response :success + end + + test "filtered index with several terms" do + get cards_path(filters(:jz_assignments).as_params.merge(terms: ["haggis", "other"])) assert_response :success end