Class: Inquirex::DSL::StepBuilder

Inherits:
Object
  • Object
show all
Includes:
RuleHelpers
Defined in:
lib/inquirex/dsl/step_builder.rb

Overview

Builds a single Node from a step DSL block. Used by FlowBuilder for each verb (ask, say, header, btw, warning, confirm). Includes RuleHelpers for transition conditions and skip_if expressions.

Instance Method Summary collapse

Methods included from RuleHelpers

#all, #any, #contains, #equals, #greater_than, #less_than, #not_empty

Constructor Details

#initialize(verb) ⇒ StepBuilder

Returns a new instance of StepBuilder.



11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/inquirex/dsl/step_builder.rb', line 11

def initialize(verb)
  @verb = verb
  @type = nil
  @question = nil
  @text = nil
  @options = nil
  @transitions = []
  @skip_if = nil
  @default = nil
  @compute = nil
  @widget_hints = {}
  @accumulations = []
end

Instance Method Details

#accumulate(target, lookup: nil, per_selection: nil, per_unit: nil, flat: nil) ⇒ Object

Declares how this step’s answer contributes to a named accumulator. Exactly one shape key should be provided:

lookup:        Hash of answer_value => amount (for :enum)
per_selection: Hash of option_value => amount (for :multi_enum)
per_unit:      Numeric rate (multiplied by the numeric answer)
flat:          Numeric (added when the step has any answer)

Examples:

accumulate :price, lookup: { single: 200, mfj: 400 }
accumulate :price, per_unit: 25
accumulate :price, per_selection: { c: 150, e: 75 }
accumulate :complexity, flat: 1


37
38
39
40
# File 'lib/inquirex/dsl/step_builder.rb', line 37

def accumulate(target, lookup: nil, per_selection: nil, per_unit: nil, flat: nil)
  shape, payload = pick_accumulator_shape(lookup:, per_selection:, per_unit:, flat:)
  @accumulations << Accumulation.new(target:, shape:, payload:)
end

#build(id) ⇒ Node

Builds the Node for the given step id.

Parameters:

  • id (Symbol)

Returns:



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/inquirex/dsl/step_builder.rb', line 135

def build(id)
  Node.new(
    id:,
    verb:          @verb,
    type:          resolve_type,
    question:      @question,
    text:          @text,
    options:       @options,
    transitions:   @transitions,
    skip_if:       @skip_if,
    default:       @default,
    widget_hints:  resolve_widget_hints,
    accumulations: @accumulations
  )
end

#compute {|Answers| ... } ⇒ Object

Registers a compute block: auto-calculates a value from answers, not shown to user. The computed value is stored server-side only and stripped from JSON serialization.

Yields:

  • (Answers)

    block receiving answers, must return the computed value



127
128
129
# File 'lib/inquirex/dsl/step_builder.rb', line 127

def compute(&block)
  @compute = block
end

#default(value = nil, &block) ⇒ Object

Sets a default value for this step (shown pre-filled; user can change it). Can be a static value or a proc receiving collected answers so far.

Parameters:

  • value (Object, Proc) (defaults to: nil)


119
120
121
# File 'lib/inquirex/dsl/step_builder.rb', line 119

def default(value = nil, &block)
  @default = block || value
end

#options(list) ⇒ Object

Sets the list of options for :enum or :multi_enum steps. Accepts an Array (option keys) or a Hash (key => label).

Parameters:

  • list (Array, Hash)


79
80
81
# File 'lib/inquirex/dsl/step_builder.rb', line 79

def options(list)
  @options = list
end

#price(**kwargs) ⇒ Object

Sugar for the common ‘:price` accumulator. Accepts either a shape keyword (`lookup:`, `per_selection:`, `per_unit:`, `flat:`) or — when given plain option=>amount keys — treats it as a `lookup`. So both work:

price single: 200, mfj: 400           # => lookup
price per_unit: 25                    # => per_unit
price lookup: { single: 200, ... }    # => lookup (explicit)


49
50
51
52
53
54
55
56
# File 'lib/inquirex/dsl/step_builder.rb', line 49

def price(**kwargs)
  shape_keys = %i[lookup per_selection per_unit flat]
  if kwargs.keys.intersect?(shape_keys)
    accumulate(:price, **kwargs.slice(*shape_keys))
  else
    accumulate(:price, lookup: kwargs)
  end
end

#question(text) ⇒ Object

Sets the prompt/question text for collecting steps.

Parameters:

  • text (String)


66
67
68
# File 'lib/inquirex/dsl/step_builder.rb', line 66

def question(text)
  @question = text
end

#skip_if(rule) ⇒ Object

Sets a rule that skips this step entirely when true. The step is omitted from the user’s path and no answer is recorded.

Parameters:



111
112
113
# File 'lib/inquirex/dsl/step_builder.rb', line 111

def skip_if(rule)
  @skip_if = rule
end

#text(content) ⇒ Object

Sets the display text for non-collecting steps (say/header/btw/warning).

Parameters:

  • content (String)


72
73
74
# File 'lib/inquirex/dsl/step_builder.rb', line 72

def text(content)
  @text = content
end

#transition(to:, if_rule: nil, requires_server: false) ⇒ Object

Adds a conditional transition. First matching transition wins.

Parameters:

  • to (Symbol)

    target step id

  • if_rule (Rules::Base, nil) (defaults to: nil)

    condition (nil = unconditional)

  • requires_server (Boolean) (defaults to: false)

    whether this transition needs server round-trip



103
104
105
# File 'lib/inquirex/dsl/step_builder.rb', line 103

def transition(to:, if_rule: nil, requires_server: false)
  @transitions << Transition.new(target: to, rule: if_rule, requires_server:)
end

#type(value) ⇒ Object

Sets the input data type for :ask steps.

Parameters:

  • value (Symbol)

    one of Node::TYPES



60
61
62
# File 'lib/inquirex/dsl/step_builder.rb', line 60

def type(value)
  @type = value
end

#widget(type:, target: :desktop, **opts) ⇒ Object

Sets a rendering hint for the given target context. Recognized targets: :desktop, :mobile, :tty (and any future targets).

Examples:

widget target: :desktop, type: :radio_group, columns: 2
widget target: :mobile,  type: :dropdown
widget target: :tty,     type: :select

Parameters:

  • type (Symbol)

    widget type (e.g. :radio_group, :dropdown)

  • target (Symbol) (defaults to: :desktop)

    rendering context (default: :desktop)

  • opts (Hash)

    widget-specific options (e.g. columns: 2)



94
95
96
# File 'lib/inquirex/dsl/step_builder.rb', line 94

def widget(type:, target: :desktop, **opts)
  @widget_hints[target.to_sym] = WidgetHint.new(type:, options: opts)
end