Class: Protege::MessageSearch
- Inherits:
-
Object
- Object
- Protege::MessageSearch
- Defined in:
- app/services/protege/message_search.rb
Overview
Cross-persona email search behind the console's search page — a PORO service object (not an
ActiveRecord model, and not the persona-scoped search_emails agent tool).
Each field narrows the Message relation: from scans the sender, recipients spans the
to/cc/bcc lists, subject and body (text + html) scan their columns, and attachments matches
by stored filename. Filled fields are ANDed onto the same message row, so a message only matches
when it satisfies every supplied field at once. #results returns the matching messages
themselves (newest sent first) — the console lists the emails and links each to its thread — rather
than collapsing to threads, so the result grain matches the email-grained query.
Matching mirrors search_emails: case-insensitive LIKE with sanitize_sql_like so the term's
own +%+/+_+ are literals — SQLite-safe, which is the dashboard's database.
Constant Summary collapse
- FIELD_COLUMNS =
Maps each column-backed search field to the message columns it scans. Columns are a fixed allowlist, so they are safe to interpolate into the
LIKEclause (the term is a bound param). { from: %w[from_address], recipients: %w[to_addresses cc_addresses bcc_addresses], subject: %w[subject], body: %w[text_body html_body] }.freeze
Class Method Summary collapse
-
.from_params(params) ⇒ Protege::MessageSearch
Build a search from request params, reading the field keys it understands.
Instance Method Summary collapse
-
#active? ⇒ Boolean
Whether any field carries a term to search on.
-
#initialize(from: nil, recipients: nil, subject: nil, body: nil, attachments: nil) ⇒ MessageSearch
constructor
A new instance of MessageSearch.
-
#results ⇒ ActiveRecord::Relation<Protege::Message>
The matching messages, newest sent first, each with its thread preloaded for the result row; empty when no field is filled.
Constructor Details
#initialize(from: nil, recipients: nil, subject: nil, body: nil, attachments: nil) ⇒ MessageSearch
Returns a new instance of MessageSearch.
45 46 47 48 |
# File 'app/services/protege/message_search.rb', line 45 def initialize(from: nil, recipients: nil, subject: nil, body: nil, attachments: nil) @column_terms = { from:, recipients:, subject:, body: } @attachments = end |
Class Method Details
.from_params(params) ⇒ Protege::MessageSearch
Build a search from request params, reading the field keys it understands.
31 32 33 34 35 36 37 |
# File 'app/services/protege/message_search.rb', line 31 def from_params(params) new(from: params[:from], recipients: params[:recipients], subject: params[:subject], body: params[:body], attachments: params[:attachments]) end |
Instance Method Details
#active? ⇒ Boolean
Whether any field carries a term to search on.
53 54 55 |
# File 'app/services/protege/message_search.rb', line 53 def active? (@column_terms.values + [@attachments]).any?(&:present?) end |
#results ⇒ ActiveRecord::Relation<Protege::Message>
The matching messages, newest sent first, each with its thread preloaded for the result row; empty when no field is filled.
preload (a separate query) rather than includes avoids a JOIN — the search columns subject
and from_address also exist on protege_email_threads, so a join would make them ambiguous.
64 65 66 67 68 |
# File 'app/services/protege/message_search.rb', line 64 def results return Message.none unless active? .preload(:email_thread).order(sent_at: :desc) end |