Class: Inquirex::Node
- Inherits:
-
Object
- Object
- Inquirex::Node
- Defined in:
- lib/inquirex/node.rb
Overview
A single step in the flow. The verb determines the role of this node:
Collecting verbs (user provides input):
:ask — typed question with one of the 11 data types
:confirm — yes/no boolean gate (shorthand for ask with type :boolean)
Display verbs (no input, auto-advance):
:say — informational message
:header — section heading or title card
:btw — admonition, sidebar, or contextual note
:warning — important alert
Constant Summary collapse
- VERBS =
Valid DSL verbs and which ones collect input from the user.
%i[ask say header btw warning confirm].freeze
- COLLECTING_VERBS =
%i[ask confirm].freeze
- DISPLAY_VERBS =
%i[say header btw warning].freeze
- TYPES =
Valid data types for :ask steps.
%i[ string text integer decimal currency boolean enum multi_enum date email phone ].freeze
Instance Attribute Summary collapse
-
#accumulations ⇒ Object
readonly
Returns the value of attribute accumulations.
-
#default ⇒ Object?
readonly
default value (pre-fill, user can change).
-
#id ⇒ Symbol
readonly
unique step identifier.
-
#option_labels ⇒ Hash?
readonly
key => display label mapping.
-
#options ⇒ Array?
readonly
option keys for :enum/:multi_enum steps.
-
#question ⇒ String?
readonly
prompt text for collecting steps.
-
#skip_if ⇒ Rules::Base?
readonly
rule to skip this step entirely.
-
#text ⇒ String?
readonly
display text for non-collecting steps.
-
#transitions ⇒ Array<Transition>
readonly
ordered conditional next-step edges.
-
#type ⇒ Symbol?
readonly
input type for :ask/:confirm (nil for display verbs).
-
#verb ⇒ Symbol
readonly
DSL verb (:ask, :say, :header, :btw, :warning, :confirm).
-
#widget_hints ⇒ Hash{Symbol => WidgetHint}?
readonly
rendering hints per target.
Class Method Summary collapse
-
.from_h(id, hash) ⇒ Node
Deserializes a node from a plain Hash.
Instance Method Summary collapse
-
#collecting? ⇒ Boolean
True if this step collects input from the user.
-
#display? ⇒ Boolean
True if this step only displays content (no input).
-
#effective_widget_hint_for(target: :desktop) ⇒ WidgetHint?
Returns the explicit hint for the target, falling back to the registry default for this node’s type when no explicit hint is set.
-
#initialize(id:, verb:, type: nil, question: nil, text: nil, options: nil, transitions: [], skip_if: nil, default: nil, widget_hints: nil, accumulations: []) ⇒ Node
constructor
A new instance of Node.
-
#next_step_id(answers) ⇒ Symbol?
Resolves the next step id from current answers by evaluating transitions in order.
-
#skip?(answers) ⇒ Boolean
Whether this step should be skipped given current answers.
-
#to_h ⇒ Hash
Serializes the node to a plain Hash for JSON output.
-
#widget_hint_for(target: :desktop) ⇒ WidgetHint?
Returns the explicit widget hint for the given target, or nil.
Constructor Details
#initialize(id:, verb:, type: nil, question: nil, text: nil, options: nil, transitions: [], skip_if: nil, default: nil, widget_hints: nil, accumulations: []) ⇒ Node
Returns a new instance of Node.
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/inquirex/node.rb', line 52 def initialize(id:, verb:, type: nil, question: nil, text: nil, options: nil, transitions: [], skip_if: nil, default: nil, widget_hints: nil, accumulations: []) @id = id.to_sym @verb = verb.to_sym @type = type&.to_sym @question = question @text = text @transitions = transitions.freeze @skip_if = skip_if @default = default @widget_hints = &.freeze @accumulations = accumulations.freeze () freeze end |
Instance Attribute Details
#accumulations ⇒ Object (readonly)
Returns the value of attribute accumulations.
39 40 41 |
# File 'lib/inquirex/node.rb', line 39 def accumulations @accumulations end |
#default ⇒ Object? (readonly)
default value (pre-fill, user can change)
27 28 29 |
# File 'lib/inquirex/node.rb', line 27 def default @default end |
#id ⇒ Symbol (readonly)
unique step identifier
27 28 29 |
# File 'lib/inquirex/node.rb', line 27 def id @id end |
#option_labels ⇒ Hash? (readonly)
key => display label mapping
27 28 29 |
# File 'lib/inquirex/node.rb', line 27 def option_labels @option_labels end |
#options ⇒ Array? (readonly)
option keys for :enum/:multi_enum steps
27 28 29 |
# File 'lib/inquirex/node.rb', line 27 def @options end |
#question ⇒ String? (readonly)
prompt text for collecting steps
27 28 29 |
# File 'lib/inquirex/node.rb', line 27 def question @question end |
#skip_if ⇒ Rules::Base? (readonly)
rule to skip this step entirely
27 28 29 |
# File 'lib/inquirex/node.rb', line 27 def skip_if @skip_if end |
#text ⇒ String? (readonly)
display text for non-collecting steps
27 28 29 |
# File 'lib/inquirex/node.rb', line 27 def text @text end |
#transitions ⇒ Array<Transition> (readonly)
ordered conditional next-step edges
27 28 29 |
# File 'lib/inquirex/node.rb', line 27 def transitions @transitions end |
#type ⇒ Symbol? (readonly)
input type for :ask/:confirm (nil for display verbs)
27 28 29 |
# File 'lib/inquirex/node.rb', line 27 def type @type end |
#verb ⇒ Symbol (readonly)
DSL verb (:ask, :say, :header, :btw, :warning, :confirm)
27 28 29 |
# File 'lib/inquirex/node.rb', line 27 def verb @verb end |
#widget_hints ⇒ Hash{Symbol => WidgetHint}? (readonly)
rendering hints per target
27 28 29 |
# File 'lib/inquirex/node.rb', line 27 def @widget_hints end |
Class Method Details
.from_h(id, hash) ⇒ Node
Deserializes a node from a plain Hash.
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/inquirex/node.rb', line 161 def self.from_h(id, hash) verb = hash["verb"] || hash[:verb] type = hash["type"] || hash[:type] question = hash["question"] || hash[:question] text = hash["text"] || hash[:text] = hash["options"] || hash[:options] transitions_data = hash["transitions"] || hash[:transitions] || [] skip_if_data = hash["skip_if"] || hash[:skip_if] default = hash["default"] || hash[:default] = hash["widget"] || hash[:widget] accumulate_data = hash["accumulate"] || hash[:accumulate] transitions = transitions_data.map { |t| Transition.from_h(t) } skip_if = skip_if_data ? Rules::Base.from_h(skip_if_data) : nil = () = () accumulations = deserialize_accumulations(accumulate_data) new( id:, verb:, type:, question:, text:, options:, transitions:, skip_if:, default:, widget_hints:, accumulations: ) end |
Instance Method Details
#collecting? ⇒ Boolean
Returns true if this step collects input from the user.
78 79 80 |
# File 'lib/inquirex/node.rb', line 78 def collecting? COLLECTING_VERBS.include?(@verb) end |
#display? ⇒ Boolean
Returns true if this step only displays content (no input).
83 84 85 |
# File 'lib/inquirex/node.rb', line 83 def display? DISPLAY_VERBS.include?(@verb) end |
#effective_widget_hint_for(target: :desktop) ⇒ WidgetHint?
Returns the explicit hint for the target, falling back to the registry default for this node’s type when no explicit hint is set.
100 101 102 |
# File 'lib/inquirex/node.rb', line 100 def (target: :desktop) (target:) || WidgetRegistry.default_hint_for(@type, context: target) end |
#next_step_id(answers) ⇒ Symbol?
Resolves the next step id from current answers by evaluating transitions in order.
108 109 110 111 |
# File 'lib/inquirex/node.rb', line 108 def next_step_id(answers) match = @transitions.find { |t| t.applies?(answers) } match&.target end |
#skip?(answers) ⇒ Boolean
Whether this step should be skipped given current answers.
117 118 119 120 121 |
# File 'lib/inquirex/node.rb', line 117 def skip?(answers) return false if @skip_if.nil? @skip_if.evaluate(answers) end |
#to_h ⇒ Hash
Serializes the node to a plain Hash for JSON output. Lambda defaults/compute are stripped (server-side only).
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/inquirex/node.rb', line 127 def to_h hash = { "verb" => @verb.to_s } if collecting? hash["type"] = @type.to_s if @type hash["question"] = @question if @question hash["options"] = if @options hash["skip_if"] = @skip_if.to_h if @skip_if hash["default"] = @default unless @default.nil? || @default.is_a?(Proc) elsif @text hash["text"] = @text end hash["transitions"] = @transitions.map(&:to_h) unless @transitions.empty? if @widget_hints && !@widget_hints.empty? hash["widget"] = @widget_hints.transform_keys(&:to_s) .transform_values(&:to_h) end unless @accumulations.empty? hash["accumulate"] = @accumulations.to_h do |acc| [acc.target.to_s, acc.to_h] end end hash end |
#widget_hint_for(target: :desktop) ⇒ WidgetHint?
Returns the explicit widget hint for the given target, or nil.
91 92 93 |
# File 'lib/inquirex/node.rb', line 91 def (target: :desktop) @widget_hints&.fetch(target.to_sym, nil) end |