Class: FlowChat::Input

Inherits:
Object
  • Object
show all
Defined in:
lib/flow_chat/input.rb

Overview

A single inbound turn.

Replaces the old "$media$"/"$location$"/"$contact$" sentinels: instead of overloading the input string with a control signal, a turn carries its text and (at most one) structured attachment as first-class fields.

It behaves like its text wherever a string method is expected — so validators/transforms written for text (input.strip, input.to_i, input.blank?) keep working — while also exposing #media, #location, #contact, and #attachment_type for the attachment. The prompt gates on #submitted? (text OR attachment), so a caption-less photo still answers a screen even though its text is blank.

Constant Summary collapse

START =

Session marker for the "first message" gate. Not a turn signal — kept as a namespaced constant so FlowChat::Input::START continues to resolve.

"$start$"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(text: nil, media: nil, location: nil, contact: nil) ⇒ Input

Returns a new instance of Input.



24
25
26
27
28
29
# File 'lib/flow_chat/input.rb', line 24

def initialize(text: nil, media: nil, location: nil, contact: nil)
  @text = text.nil? ? "" : text.to_s
  @media = media || []
  @location = location
  @contact = contact
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



78
79
80
81
82
83
84
# File 'lib/flow_chat/input.rb', line 78

def method_missing(name, *args, &block)
  if @text.respond_to?(name)
    @text.send(name, *args, &block)
  else
    super
  end
end

Instance Attribute Details

#contactObject (readonly)

#media is always an ArrayFlowChat::Media (empty when none). It is a list even on single-media platforms so callers iterate uniformly and never silently drop the extra attachments a message can carry (e.g. Intercom).



22
23
24
# File 'lib/flow_chat/input.rb', line 22

def contact
  @contact
end

#locationObject (readonly)

#media is always an ArrayFlowChat::Media (empty when none). It is a list even on single-media platforms so callers iterate uniformly and never silently drop the extra attachments a message can carry (e.g. Intercom).



22
23
24
# File 'lib/flow_chat/input.rb', line 22

def location
  @location
end

#mediaObject (readonly)

#media is always an ArrayFlowChat::Media (empty when none). It is a list even on single-media platforms so callers iterate uniformly and never silently drop the extra attachments a message can carry (e.g. Intercom).



22
23
24
# File 'lib/flow_chat/input.rb', line 22

def media
  @media
end

#textObject (readonly)

#media is always an ArrayFlowChat::Media (empty when none). It is a list even on single-media platforms so callers iterate uniformly and never silently drop the extra attachments a message can carry (e.g. Intercom).



22
23
24
# File 'lib/flow_chat/input.rb', line 22

def text
  @text
end

Instance Method Details

#==(other) ⇒ Object



65
66
67
68
# File 'lib/flow_chat/input.rb', line 65

def ==(other)
  other = other.to_s if other.is_a?(FlowChat::Input)
  @text == other
end

#attachmentObject

The structured payload on this turn — the media list, or the location / contact hash — or nil. Pair with #attachment_type to know which.



44
45
46
47
48
49
50
# File 'lib/flow_chat/input.rb', line 44

def attachment
  case attachment_type
  when :media then media
  when :location then location
  when :contact then contact
  end
end

#attachment?Boolean

Returns:

  • (Boolean)


38
39
40
# File 'lib/flow_chat/input.rb', line 38

def attachment?
  !attachment_type.nil?
end

#attachment_typeObject

The kind of structured payload on this turn, or nil. At most one is ever present in a single message, so this is a safe discriminator.



54
55
56
57
58
59
# File 'lib/flow_chat/input.rb', line 54

def attachment_type
  return :media if @media.any?
  return :location if @location
  return :contact if @contact
  nil
end

#respond_to_missing?(name, include_private = false) ⇒ Boolean

Behave like the text for any other PUBLIC string method (strip, to_i, match?, length, empty?, ...), so text-oriented validators/transforms keep working. Private String methods are not exposed — respond_to_missing? and method_missing agree on public-only so respond_to? never lies.

Returns:

  • (Boolean)


74
75
76
# File 'lib/flow_chat/input.rb', line 74

def respond_to_missing?(name, include_private = false)
  @text.respond_to?(name) || super
end

#submitted?Boolean

Did the user send anything this turn — text OR an attachment? The prompt gates on this so a caption-less photo answers a screen. Distinct from #present?/#blank?, which follow the text (so text validators behave).

Returns:

  • (Boolean)


34
35
36
# File 'lib/flow_chat/input.rb', line 34

def 
  !@text.empty? || attachment?
end

#to_sObject



61
62
63
# File 'lib/flow_chat/input.rb', line 61

def to_s
  @text
end