Class: Inquirex::Definition

Inherits:
Object
  • Object
show all
Defined in:
lib/inquirex/definition.rb

Overview

Immutable, versionable flow graph. Maps step ids to Node objects and defines the entry point. Carries optional metadata (id, version, title, subtitle, brand) for the JS widget. Supports JSON round-trip serialization; lambdas are stripped on serialization.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(start_step_id:, nodes:, id: nil, version: "1.0.0", meta: {}, accumulators: {}, send_emails: []) ⇒ Definition

Returns a new instance of Definition.

Parameters:

  • start_step_id (Symbol)

    id of the initial step

  • nodes (Hash<Symbol, Node>)

    all steps keyed by id

  • id (String, nil) (defaults to: nil)

    flow identifier

  • version (String) (defaults to: "1.0.0")

    semver

  • meta (Hash) (defaults to: {})

    frontend metadata

  • accumulators (Hash<Symbol, Accumulator>) (defaults to: {})

    named running totals

  • send_emails (Array<SendEmail>) (defaults to: [])

    emails the host application builds after completion, in declaration order

Raises:



33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/inquirex/definition.rb', line 33

def initialize(start_step_id:, nodes:, id: nil, version: "1.0.0", meta: {},
  accumulators: {}, send_emails: [])
  @id = id
  @version = version
  @meta = meta.freeze
  @start_step_id = start_step_id.to_sym
  @steps = nodes.freeze
  @accumulators = accumulators.freeze
  @send_emails = send_emails.freeze
  validate!
  freeze
end

Instance Attribute Details

#accumulatorsObject (readonly)

Returns the value of attribute accumulators.



16
17
18
# File 'lib/inquirex/definition.rb', line 16

def accumulators
  @accumulators
end

#idString? (readonly)

flow identifier (e.g. "tax-intake-2025")

Returns:

  • (String, nil)

    the current value of id



15
16
17
# File 'lib/inquirex/definition.rb', line 15

def id
  @id
end

#metaHash (readonly)

title, subtitle, brand info for the frontend

Returns:

  • (Hash)

    the current value of meta



15
16
17
# File 'lib/inquirex/definition.rb', line 15

def meta
  @meta
end

#send_emailsObject (readonly)

Returns the value of attribute send_emails.



16
17
18
# File 'lib/inquirex/definition.rb', line 16

def send_emails
  @send_emails
end

#start_step_idSymbol (readonly)

id of the first step in the flow

Returns:

  • (Symbol)

    the current value of start_step_id



15
16
17
# File 'lib/inquirex/definition.rb', line 15

def start_step_id
  @start_step_id
end

#stepsHash<Symbol, Node> (readonly)

frozen map of step id => node

Returns:

  • (Hash<Symbol, Node>)

    the current value of steps



15
16
17
# File 'lib/inquirex/definition.rb', line 15

def steps
  @steps
end

#versionString (readonly)

semver string (default: "1.0.0")

Returns:

  • (String)

    the current value of version



15
16
17
# File 'lib/inquirex/definition.rb', line 15

def version
  @version
end

Class Method Details

.from_h(hash) ⇒ Definition

Deserializes a Definition from a plain Hash.

Parameters:

  • hash (Hash)

    definition attributes (string or symbol keys)

Returns:



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/inquirex/definition.rb', line 104

def self.from_h(hash)
  id = hash["id"] || hash[:id]
  version = hash["version"] || hash[:version] || "1.0.0"
  meta = hash["meta"] || hash[:meta] || {}
  start = hash["start"] || hash[:start]
  steps_data = hash["steps"] || hash[:steps] || {}
  acc_data = hash["accumulators"] || hash[:accumulators] || {}
  emails_data = hash["send_emails"] || hash[:send_emails] || []

  nodes = steps_data.each_with_object({}) do |(step_id, step_hash), acc|
    sym_id = step_id.to_sym
    acc[sym_id] = Node.from_h(sym_id, step_hash)
  end

  accumulators = acc_data.each_with_object({}) do |(name, entry), h|
    sym = name.to_sym
    h[sym] = Accumulator.from_h(sym, entry)
  end

  send_emails = emails_data.map { |entry| SendEmail.from_h(entry) }

  new(start_step_id: start,
    nodes:,
    id:,
    version:,
    meta:,
    accumulators:,
    send_emails:)
end

.from_json(json) ⇒ Definition

Deserializes a Definition from a JSON string.

Parameters:

  • json (String)

    JSON representation

Returns:



94
95
96
97
98
# File 'lib/inquirex/definition.rb', line 94

def self.from_json(json)
  from_h(JSON.parse(json))
rescue JSON::ParserError => e
  raise Errors::SerializationError, "Invalid JSON: #{e.message}"
end

Instance Method Details

#start_stepNode

Returns the node for the start step.

Returns:

  • (Node)

    the node for the start step



47
48
49
# File 'lib/inquirex/definition.rb', line 47

def start_step
  step(@start_step_id)
end

#step(id) ⇒ Node

Returns the node for that step.

Parameters:

  • id (Symbol)

    step id

Returns:

  • (Node)

    the node for that step

Raises:



54
55
56
# File 'lib/inquirex/definition.rb', line 54

def step(id)
  @steps.fetch(id.to_sym) { raise Errors::UnknownStepError, "Unknown step: #{id.inspect}" }
end

#step_idsArray<Symbol>

Returns all step ids.

Returns:

  • (Array<Symbol>)

    all step ids



59
60
61
# File 'lib/inquirex/definition.rb', line 59

def step_ids
  @steps.keys
end

#to_hHash

Serializes to a plain Hash.

Returns:

  • (Hash)


74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/inquirex/definition.rb', line 74

def to_h
  hash = {}
  hash["id"] = @id if @id
  hash["version"] = @version
  hash["meta"] = @meta unless @meta.empty?
  hash["start"] = @start_step_id.to_s
  unless @accumulators.empty?
    hash["accumulators"] = @accumulators.each_with_object({}) do |(name, acc), h|
      h[name.to_s] = acc.to_h
    end
  end
  hash["steps"] = @steps.transform_keys(&:to_s).transform_values(&:to_h)
  hash["send_emails"] = @send_emails.map(&:to_h) unless @send_emails.empty?
  hash
end

#to_jsonString

Serializes the definition to a JSON string. Lambdas (default procs, compute blocks) are silently stripped.

Returns:

  • (String)

    JSON representation



67
68
69
# File 'lib/inquirex/definition.rb', line 67

def to_json(*)
  JSON.generate(to_h)
end