Skip to content

Commit dfa4875

Browse files
authored
Merge pull request #2418 from basecamp/filter-drafts-in-search
Exclude draft cards from search index
2 parents f6211db + a9c6bc2 commit dfa4875

File tree

7 files changed

+107
-2
lines changed

7 files changed

+107
-2
lines changed

app/models/card/searchable.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,8 @@ def search_card_id
2525
def search_board_id
2626
board_id
2727
end
28+
29+
def searchable?
30+
published?
31+
end
2832
end

app/models/comment/searchable.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,8 @@ def search_card_id
2020
def search_board_id
2121
card.board_id
2222
end
23+
24+
def searchable?
25+
card.published?
26+
end
2327
end

app/models/concerns/searchable.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,17 @@ def reindex
1515

1616
private
1717
def create_in_search_index
18-
search_record_class.create!(search_record_attributes)
18+
if searchable?
19+
search_record_class.create!(search_record_attributes)
20+
end
1921
end
2022

2123
def update_in_search_index
22-
search_record_class.upsert!(search_record_attributes)
24+
if searchable?
25+
search_record_class.upsert!(search_record_attributes)
26+
else
27+
remove_from_search_index
28+
end
2329
end
2430

2531
def remove_from_search_index
@@ -53,4 +59,5 @@ def search_record_class
5359
# - search_content: returns content string
5460
# - search_card_id: returns the card id (self.id for cards, card_id for comments)
5561
# - search_board_id: returns the board id
62+
# - searchable?: returns whether this record should be indexed
5663
end
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env ruby
2+
3+
require_relative "../../config/environment"
4+
5+
total_deleted = 0
6+
7+
Account.find_each do |account|
8+
search_record_class = Search::Record.for(account.id)
9+
10+
# Find search records for draft cards (both Card and Comment searchables)
11+
draft_card_ids = Card.where(account_id: account.id, status: "drafted").pluck(:id)
12+
13+
if draft_card_ids.any?
14+
count = search_record_class.where(card_id: draft_card_ids).delete_all
15+
if count > 0
16+
puts "#{account.name}: deleted #{count} search records for draft cards"
17+
total_deleted += count
18+
end
19+
end
20+
end
21+
22+
puts "Migration completed! Total deleted: #{total_deleted}"

test/models/card/searchable_test.rb

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@
33
class Card::SearchableTest < ActiveSupport::TestCase
44
include SearchTestHelper
55

6+
test "searchable? returns true for published cards" do
7+
card = @board.cards.create!(title: "Published Card", status: "published", creator: @user)
8+
assert card.searchable?
9+
end
10+
11+
test "searchable? returns false for draft cards" do
12+
card = @board.cards.create!(title: "Draft Card", status: "drafted", creator: @user)
13+
assert_not card.searchable?
14+
end
15+
616
test "card search" do
717
# Searching by title
818
card = @board.cards.create!(title: "layout is broken", status: "published", creator: @user)
@@ -78,4 +88,46 @@ class Card::SearchableTest < ActiveSupport::TestCase
7888
assert_equal 0, fts_count, "FTS entry should be deleted"
7989
end
8090
end
91+
92+
test "updating a draft card does not index it" do
93+
search_record_class = Search::Record.for(@user.account_id)
94+
95+
card = @board.cards.create!(title: "Draft card", creator: @user, status: "drafted")
96+
assert_nil search_record_class.find_by(searchable_type: "Card", searchable_id: card.id)
97+
98+
card.update!(title: "Updated draft card")
99+
assert_nil search_record_class.find_by(searchable_type: "Card", searchable_id: card.id),
100+
"Draft card should not be indexed after update"
101+
102+
results = Card.mentioning("Updated", user: @user)
103+
assert_not_includes results, card
104+
end
105+
106+
test "publishing a draft card indexes it" do
107+
search_record_class = Search::Record.for(@user.account_id)
108+
109+
card = @board.cards.create!(title: "Draft to publish", creator: @user, status: "drafted")
110+
assert_nil search_record_class.find_by(searchable_type: "Card", searchable_id: card.id)
111+
112+
card.publish
113+
search_record = search_record_class.find_by(searchable_type: "Card", searchable_id: card.id)
114+
assert_not_nil search_record, "Published card should be indexed"
115+
assert_equal card.id, search_record.card_id
116+
117+
results = Card.mentioning("publish", user: @user)
118+
assert_includes results, card
119+
end
120+
121+
test "unpublishing a draft card removes it from the search index" do
122+
search_record_class = Search::Record.for(@user.account_id)
123+
124+
card = @board.cards.create!(title: "Draft to publish", creator: @user, status: "published")
125+
assert_not_nil search_record_class.find_by(searchable_type: "Card", searchable_id: card.id)
126+
127+
card.update!(status: "drafted")
128+
129+
assert_nil search_record_class.find_by(searchable_type: "Card", searchable_id: card.id)
130+
results = Card.mentioning("publish", user: @user)
131+
assert_not_includes results, card
132+
end
81133
end

test/models/comment/searchable_test.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,17 @@ class Comment::SearchableTest < ActiveSupport::TestCase
77
@card = @board.cards.create!(title: "Test Card", status: "published", creator: @user)
88
end
99

10+
test "searchable? returns true for comments on published cards" do
11+
comment = @card.comments.create!(body: "test comment", creator: @user)
12+
assert comment.searchable?
13+
end
14+
15+
test "searchable? returns false for comments on draft cards" do
16+
draft_card = @board.cards.create!(title: "Draft Card", status: "drafted", creator: @user)
17+
comment = draft_card.comments.build(body: "test comment", creator: @user)
18+
assert_not comment.searchable?
19+
end
20+
1021
test "comment search" do
1122
search_record_class = Search::Record.for(@user.account_id)
1223
# Comment is indexed on create

test/models/search_test.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ class SearchTest < ActiveSupport::TestCase
1515
results = Search::Record.for(@user.account_id).search("overflowing", user: @user)
1616
assert results.find { |it| it.card_id == comment_card.id && it.searchable_type == "Comment" }
1717

18+
# Drafted cards are excluded from search results
19+
drafted_card = @board.cards.create!(title: "drafted searchable content", creator: @user, status: "drafted")
20+
results = Search::Record.for(@user.account_id).search("drafted", user: @user)
21+
assert_not results.find { |it| it.card_id == drafted_card.id }
22+
1823
# Don't include inaccessible boards
1924
other_user = User.create!(name: "Other User", account: @account)
2025
inaccessible_board = Board.create!(name: "Inaccessible Board", account: @account, creator: other_user)

0 commit comments

Comments
 (0)