Module: RubyLLM::ActiveRecord::MessageMethods

Extended by:
ActiveSupport::Concern
Includes:
AttachmentHelpers, PayloadHelpers
Defined in:
lib/ruby_llm/active_record/message_methods.rb

Overview

Maps an application-owned message record onto RubyLLM's public Message API while keeping accounting and tool-call rows private to the gem.

Instance Method Summary collapse

Instance Method Details

#cache_until_hereObject

Marks the message as a prompt cache boundary and returns it.



56
57
58
59
# File 'lib/ruby_llm/active_record/message_methods.rb', line 56

def cache_until_here
  update!(cache_until_here: true)
  self
end

#cache_until_here?Boolean

Returns true if the message is a prompt cache boundary.

Returns:

  • (Boolean)


62
63
64
# File 'lib/ruby_llm/active_record/message_methods.rb', line 62

def cache_until_here?
  optional_column(:cache_until_here) || false
end

#chat_associationObject

:nodoc:



16
17
18
# File 'lib/ruby_llm/active_record/message_methods.rb', line 16

def chat_association # :nodoc:
  send(chat_association_name)
end

#citationsObject

Returns the citations as an array of RubyLLM::Citation.



75
76
77
# File 'lib/ruby_llm/active_record/message_methods.rb', line 75

def citations
  Array(optional_column(:citations)).map { |citation| RubyLLM::Citation.from_h(citation) }
end

#content_filtered?Boolean

Returns true if a provider safety filter stopped the response.

Returns:

  • (Boolean)


160
161
162
# File 'lib/ruby_llm/active_record/message_methods.rb', line 160

def content_filtered?
  to_llm.content_filtered?
end

#costObject

Returns the cost across every attempt that produced the message, as a RubyLLM::Cost.



90
91
92
93
# File 'lib/ruby_llm/active_record/message_methods.rb', line 90

def cost
  records = ruby_llm_usages.to_a
  RubyLLM::Cost.aggregate(records.map(&:cost), complete: records.all?(&:cost_available?))
end

#finish_reasonObject

Returns why the model stopped, as the Symbol RubyLLM::Message#finish_reason reports.



140
141
142
# File 'lib/ruby_llm/active_record/message_methods.rb', line 140

def finish_reason
  optional_column(:finish_reason)&.to_sym
end

#max_tokens?Boolean

Returns true if a token limit stopped the response.

Returns:

  • (Boolean)


150
151
152
# File 'lib/ruby_llm/active_record/message_methods.rb', line 150

def max_tokens?
  to_llm.max_tokens?
end

#modelObject

Returns the model ID from the last successful attempt, or nil.



46
47
48
# File 'lib/ruby_llm/active_record/message_methods.rb', line 46

def model
  to_llm.model
end

#model_infoObject

Returns the model from the registry, or nil if it is unknown.



51
52
53
# File 'lib/ruby_llm/active_record/message_methods.rb', line 51

def model_info
  to_llm.model_info
end

#parent_tool_callObject

Returns the tool call this message answers, or nil.



101
102
103
# File 'lib/ruby_llm/active_record/message_methods.rb', line 101

def parent_tool_call
  ruby_llm_parent_tool_call&.to_llm
end

#parsedObject

Returns the content parsed as JSON, or nil when the message has no text.



165
166
167
168
169
170
# File 'lib/ruby_llm/active_record/message_methods.rb', line 165

def parsed
  text = extract_content
  return if text.nil? || text.empty?

  JSON.parse(text)
end

#ruby_llm_usage_entriesObject

:nodoc:



41
42
43
# File 'lib/ruby_llm/active_record/message_methods.rb', line 41

def ruby_llm_usage_entries # :nodoc:
  ruby_llm_usages.map(&:to_entry)
end

#server_tool_callsObject

Returns the provider-executed tool steps as an array of RubyLLM::ServerToolCall.



80
81
82
# File 'lib/ruby_llm/active_record/message_methods.rb', line 80

def server_tool_calls
  Array(optional_column(:server_tool_calls)).map { |call| RubyLLM::ServerToolCall.from_h(call) }
end

#stopped?Boolean

Returns true if the model finished normally without requesting tools.

Returns:

  • (Boolean)


145
146
147
# File 'lib/ruby_llm/active_record/message_methods.rb', line 145

def stopped?
  to_llm.stopped?
end

#thinkingObject

Returns the reasoning the model returned as a RubyLLM::Thinking, or nil.



67
68
69
70
71
72
# File 'lib/ruby_llm/active_record/message_methods.rb', line 67

def thinking
  RubyLLM::Thinking.build(
    text: optional_column(:thinking_text),
    signature: optional_column(:thinking_signature)
  )
end

#to_llmObject

Converts this record to a RubyLLM::Message.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/ruby_llm/active_record/message_methods.rb', line 21

def to_llm
  entries = ruby_llm_usage_entries
  RubyLLM::Message.new(
    role: role.to_sym,
    content: extract_content,
    attachments: extract_attachments,
    thinking: thinking,
    citations: citations,
    server_tool_calls: server_tool_calls,
    raw_content: optional_column(:raw_content),
    raw_reasoning: optional_column(:raw_reasoning),
    usage_entries: entries,
    tool_calls: tool_calls,
    tool_call_id: parent_tool_call&.id,
    finish_reason: optional_column(:finish_reason),
    model: entries.reverse.find(&:succeeded?)&.model,
    cache_until_here: cache_until_here?
  )
end

#to_partial_pathObject

Returns the partial path for the message by role, such as messages/assistant or messages/tool_calls.



122
123
124
125
126
127
128
129
130
131
132
# File 'lib/ruby_llm/active_record/message_methods.rb', line 122

def to_partial_path
  partial_prefix = self.class.name.underscore.pluralize
  role_partial = if tool_call?
                   'tool_calls'
                 elsif role.to_s == 'tool'
                   'tool'
                 else
                   role.to_s.presence || 'assistant'
                 end
  "#{partial_prefix}/#{role_partial}"
end

#tokensObject

Returns the token usage across every attempt that produced the message.



85
86
87
# File 'lib/ruby_llm/active_record/message_methods.rb', line 85

def tokens
  RubyLLM::Tokens.aggregate(ruby_llm_usages.map(&:tokens))
end

#tool_call?Boolean

Returns true if the message carries tool calls.

Returns:

  • (Boolean)


111
112
113
# File 'lib/ruby_llm/active_record/message_methods.rb', line 111

def tool_call?
  ruby_llm_tool_calls.any?
end

#tool_call_stop?Boolean

Returns true if the model stopped to request tool calls.

Returns:

  • (Boolean)


155
156
157
# File 'lib/ruby_llm/active_record/message_methods.rb', line 155

def tool_call_stop?
  to_llm.tool_call_stop?
end

#tool_callsObject

Returns the tool calls as RubyLLM::ToolCall values keyed by call id.



96
97
98
# File 'lib/ruby_llm/active_record/message_methods.rb', line 96

def tool_calls
  ruby_llm_tool_calls.to_h { |record| [record.tool_call_id, record.to_llm] }
end

#tool_error_messageObject

Returns the error text of a failed tool result, or nil.



135
136
137
# File 'lib/ruby_llm/active_record/message_methods.rb', line 135

def tool_error_message
  payload_error_message(extract_content)
end

#tool_result?Boolean

Returns true if the message answers a tool call.

Returns:

  • (Boolean)


116
117
118
# File 'lib/ruby_llm/active_record/message_methods.rb', line 116

def tool_result?
  ruby_llm_parent_tool_call.present?
end

#tool_resultsObject

Returns the message records that answer this message's tool calls.



106
107
108
# File 'lib/ruby_llm/active_record/message_methods.rb', line 106

def tool_results
  ruby_llm_tool_calls.filter_map(&:result)
end