Files
fizzy/app/models/search/record.rb
T
2025-11-17 09:12:41 -05:00

91 lines
2.2 KiB
Ruby

class Search::Record < ApplicationRecord
self.abstract_class = true
SHARD_COUNT = 16
SHARD_CLASSES = SHARD_COUNT.times.map do |shard_id|
Class.new(self) do
self.table_name = "search_records_#{shard_id}"
def self.name
"Search::Record"
end
end
end.freeze
belongs_to :searchable, polymorphic: true
belongs_to :card
# Virtual attributes from search query
attribute :query, :string
validates :account_id, :searchable_type, :searchable_id, :card_id, :board_id, :created_at, presence: true
class << self
def for_account(account_id)
SHARD_CLASSES[shard_id_for_account(account_id)]
end
def shard_id_for_account(account_id)
Zlib.crc32(account_id.to_s) % SHARD_COUNT
end
def card_join
"INNER JOIN #{table_name} ON #{table_name}.card_id = cards.id"
end
end
scope :for_query, ->(query:, user:) do
if query.valid? && user.board_ids.any?
matching(query.to_s).for_user(user)
else
none
end
end
scope :matching, ->(query) do
where("MATCH(#{table_name}.content, #{table_name}.title) AGAINST(? IN BOOLEAN MODE)", query)
end
scope :for_user, ->(user) do
where(account_id: user.account_id, board_id: user.board_ids)
end
scope :search, ->(query:, user:) do
for_query(query: query, user: user)
.includes(:searchable, card: [ :board, :creator ])
.select(:id, :searchable_type, :searchable_id, :card_id, :board_id, :account_id, :created_at, "#{connection.quote(query.terms)} AS query")
.order(created_at: :desc)
end
def source
searchable_type == "Comment" ? searchable : card
end
def comment
searchable if searchable_type == "Comment"
end
def card_title
highlight(card.title, show: :full) if card_id
end
def card_description
highlight(card.description.to_plain_text, show: :snippet) if card_id
end
def comment_body
highlight(comment.body.to_plain_text, show: :snippet) if comment
end
private
def highlight(text, show:)
if text.present? && attribute?(:query)
highlighter = Search::Highlighter.new(query)
show == :snippet ? highlighter.snippet(text) : highlighter.highlight(text)
else
text
end
end
end