Class: Protege::EmailThread

Inherits:
ApplicationRecord show all
Includes:
BroadcastableThread
Defined in:
app/models/protege/email_thread.rb

Overview

Groups every Message belonging to a single email conversation.

A thread is identified by its canonical thread_id: the RFC 2822 Message-ID of the conversation root. For a reply that is the first entry of the References chain (falling back to In-Reply-To); for a brand-new conversation it is the message's own Message-ID. Threads belong to one Persona and carry denormalised counters (+message_count+, last_message_at) that Message keeps fresh so the inbox can sort and display without aggregating on every render.

Constant Summary

Constants included from BroadcastableThread

BroadcastableThread::STREAM

Class Method Summary collapse

Instance Method Summary collapse

Methods included from BroadcastableThread

#broadcast_thread_created, #broadcast_thread_removed, #broadcast_thread_updated

Class Method Details

.find_or_create_for(mail:, persona:) ⇒ Protege::EmailThread

Find or create the thread for the given mail and persona.

On creation, seeds the persona, subject, and last-activity timestamp from the mail.

Parameters:

  • mail (Mail::Message)

    the email being threaded

  • persona (Protege::Persona)

    the persona that owns the conversation

Returns:

Raises:

  • (ActiveRecord::RecordInvalid)

    when a new thread fails validation



72
73
74
75
76
77
78
# File 'app/models/protege/email_thread.rb', line 72

def find_or_create_for(mail:, persona:)
  find_or_create_by!(thread_id: thread_id_for(mail)) do |t|
    t.persona         = persona
    t.subject         = mail.subject.to_s
    t.last_message_at = Time.current
  end
end

.thread_id_for(mail) ⇒ String

Derive the canonical RFC 2822 thread-root ID from a mail object.

Checks the References chain first (its head is the conversation root), then In-Reply-To, then falls back to the message's own Message-ID for a new conversation. The result is normalized through Gateway::Mail so every thread id is stored in canonical angle-bracketed form regardless of how the raw header was punctuated.

Parameters:

  • mail (Mail::Message)

    the email to inspect

Returns:

  • (String)

    the canonical, angle-bracketed thread identifier



59
60
61
62
# File 'app/models/protege/email_thread.rb', line 59

def thread_id_for(mail)
  Gateway.reference_ids(mail.references).first ||
    Gateway.canonical_message_id(mail.in_reply_to.presence || mail.message_id)
end

Instance Method Details

#latest_messageProtege::Message?

Return the most recently sent message in the thread.

Returns:



43
44
45
# File 'app/models/protege/email_thread.rb', line 43

def latest_message
  messages.order(:sent_at).last
end