Class: Livechat::Conversation
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- Livechat::Conversation
- Defined in:
- app/models/livechat/conversation.rb
Overview
One thread per visitor — like a phone line, not a ticket queue. A visitor writing into a resolved conversation reopens it; history stays in place. Visitor identity is loose (no foreign key to the host's user table): signed-in visitors are keyed by visitor_id, guests by a cookie token.
Constant Summary collapse
- STATUSES =
%w[open resolved].freeze
Class Method Summary collapse
-
.claim!(visitor_token:, visitor_id:, visitor_label: nil) ⇒ Object
A guest who signs in keeps their conversation: threads started under the cookie token are adopted by the user, once, permanently.
-
.for_visitor(visitor_id: nil, visitor_token: nil) ⇒ Object
The visitor's ongoing thread.
Instance Method Summary collapse
- #display_name ⇒ Object
- #mark_read_for_agent! ⇒ Object
- #mark_read_for_visitor! ⇒ Object
- #post_agent_message!(body:, agent_id:, agent_label:, files: nil) ⇒ Object
- #post_visitor_message!(body, files: nil) ⇒ Object
-
#register_message(message) ⇒ Object
Denormalized inbox-list fields, refreshed on every message.
- #reopen_by!(agent_label) ⇒ Object
- #resolve_by!(agent_label) ⇒ Object
- #unread_from_visitor_count ⇒ Object
Class Method Details
.claim!(visitor_token:, visitor_id:, visitor_label: nil) ⇒ Object
A guest who signs in keeps their conversation: threads started under the cookie token are adopted by the user, once, permanently.
38 39 40 41 42 43 |
# File 'app/models/livechat/conversation.rb', line 38 def self.claim!(visitor_token:, visitor_id:, visitor_label: nil) return if visitor_token.blank? || visitor_id.blank? where(visitor_token: visitor_token, visitor_id: nil) .update_all(visitor_id: visitor_id.to_s, visitor_label: visitor_label) end |
.for_visitor(visitor_id: nil, visitor_token: nil) ⇒ Object
The visitor's ongoing thread. Signed-in identity wins; guests are found by their cookie token (only unclaimed threads — a token that has been adopted by a user belongs to that user now).
28 29 30 31 32 33 34 |
# File 'app/models/livechat/conversation.rb', line 28 def self.for_visitor(visitor_id: nil, visitor_token: nil) if visitor_id.present? where(visitor_id: visitor_id.to_s).order(id: :desc).first elsif visitor_token.present? where(visitor_token: visitor_token, visitor_id: nil).order(id: :desc).first end end |
Instance Method Details
#display_name ⇒ Object
99 100 101 |
# File 'app/models/livechat/conversation.rb', line 99 def display_name visitor_label.presence || visitor_email.presence || "Visitor ##{id}" end |
#mark_read_for_agent! ⇒ Object
91 92 93 |
# File 'app/models/livechat/conversation.rb', line 91 def mark_read_for_agent! .from_visitor.unread.update_all(read_at: Time.current) end |
#mark_read_for_visitor! ⇒ Object
95 96 97 |
# File 'app/models/livechat/conversation.rb', line 95 def mark_read_for_visitor! .from_agent.unread.update_all(read_at: Time.current) end |
#post_agent_message!(body:, agent_id:, agent_label:, files: nil) ⇒ Object
55 56 57 58 59 60 61 |
# File 'app/models/livechat/conversation.rb', line 55 def (body:, agent_id:, agent_label:, files: nil) = .new(author_type: 'agent', body: body, agent_id: agent_id.to_s, agent_label: agent_label) attach(, files) .save! end |
#post_visitor_message!(body, files: nil) ⇒ Object
45 46 47 48 49 50 51 52 53 |
# File 'app/models/livechat/conversation.rb', line 45 def (body, files: nil) transaction do update!(status: 'open') if resolved? = .new(author_type: 'visitor', body: body) attach(, files) .save! end end |
#register_message(message) ⇒ Object
Denormalized inbox-list fields, refreshed on every message. Written with update_columns: cheap, no callbacks, no updated_at churn.
83 84 85 86 87 |
# File 'app/models/livechat/conversation.rb', line 83 def () updates = { last_activity_at: .created_at } updates[:last_message_preview] = .preview unless .system? update_columns(updates) end |
#reopen_by!(agent_label) ⇒ Object
72 73 74 75 76 77 78 79 |
# File 'app/models/livechat/conversation.rb', line 72 def reopen_by!(agent_label) return if open? transaction do update!(status: 'open') .create!(author_type: 'system', event: 'reopened', agent_label: agent_label) end end |
#resolve_by!(agent_label) ⇒ Object
63 64 65 66 67 68 69 70 |
# File 'app/models/livechat/conversation.rb', line 63 def resolve_by!(agent_label) return if resolved? transaction do update!(status: 'resolved') .create!(author_type: 'system', event: 'resolved', agent_label: agent_label) end end |
#unread_from_visitor_count ⇒ Object
89 |
# File 'app/models/livechat/conversation.rb', line 89 def unread_from_visitor_count = .from_visitor.unread.count |