Class: LcpRuby::Workflow::WorkflowDefinition

Inherits:
Object
  • Object
show all
Defined in:
lib/lcp_ruby/workflow/workflow_definition.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attrs = {}) ⇒ WorkflowDefinition

Returns a new instance of WorkflowDefinition.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 9

def initialize(attrs = {})
  @name = attrs[:name].to_s
  @model = attrs[:model].to_s
  @field = attrs[:field].to_s
  @version = attrs[:version] || 1
  @audit_log = attrs[:audit_log] != false
  @states = attrs[:states] || {}
  @transitions = attrs[:transitions] || {}
  @approvals = attrs[:approvals] || {}
  @timeline_states = Array(attrs[:timeline_states]).map(&:to_s).presence
  @source_path = attrs[:source_path]
  @source_type = attrs[:source_type]
  @raw_hash = attrs[:raw_hash]

  validate!
  build_transition_index!
end

Instance Attribute Details

#approvalsObject (readonly)

Returns the value of attribute approvals.



4
5
6
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 4

def approvals
  @approvals
end

#audit_logObject (readonly)

Returns the value of attribute audit_log.



4
5
6
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 4

def audit_log
  @audit_log
end

#fieldObject (readonly)

Returns the value of attribute field.



4
5
6
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 4

def field
  @field
end

#modelObject (readonly)

Returns the value of attribute model.



4
5
6
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 4

def model
  @model
end

#nameObject (readonly)

Returns the value of attribute name.



4
5
6
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 4

def name
  @name
end

#raw_hashObject (readonly)

Returns the value of attribute raw_hash.



4
5
6
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 4

def raw_hash
  @raw_hash
end

#source_pathObject

Returns the value of attribute source_path.



4
5
6
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 4

def source_path
  @source_path
end

#source_typeObject

Returns the value of attribute source_type.



4
5
6
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 4

def source_type
  @source_type
end

#statesObject (readonly)

Returns the value of attribute states.



4
5
6
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 4

def states
  @states
end

#timeline_statesObject (readonly)

Returns the value of attribute timeline_states.



4
5
6
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 4

def timeline_states
  @timeline_states
end

#transitionsObject (readonly)

Returns the value of attribute transitions.



4
5
6
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 4

def transitions
  @transitions
end

#versionObject (readonly)

Returns the value of attribute version.



4
5
6
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 4

def version
  @version
end

Class Method Details

.from_hash(hash) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 27

def self.from_hash(hash)
  hash = hash.transform_keys(&:to_s)

  states = {}
  (hash["states"] || {}).each do |state_name, state_hash|
    states[state_name.to_s] = StateDefinition.from_hash(state_name, state_hash)
  end

  transitions = {}
  (hash["transitions"] || {}).each do |trans_name, trans_hash|
    trans_hash = (trans_hash || {}).transform_keys(&:to_s)
    if trans_hash["from"] == "*"
      trans_hash = trans_hash.merge("from" => states.keys)
    end
    transitions[trans_name.to_s] = TransitionDefinition.from_hash(trans_name, trans_hash)
  end

  approvals = {}
  approvals_data = hash["approvals"]
  if approvals_data.is_a?(Hash)
    approvals_data.each do |state_name, approval_hash|
      next unless approval_hash.is_a?(Hash)
      approvals[state_name.to_s] = Approval::ApprovalDefinition.from_hash(state_name, approval_hash)
    end
  end

  new(
    name: hash["name"],
    model: hash["model"],
    field: hash["field"],
    version: hash["version"],
    audit_log: hash["audit_log"],
    states: states,
    transitions: transitions,
    approvals: approvals,
    timeline_states: hash["timeline_states"],
    raw_hash: hash
  )
end

Instance Method Details

#approval_for(state_name) ⇒ Object



83
84
85
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 83

def approval_for(state_name)
  @approvals[state_name.to_s]
end

#each_stateObject

i18n_check Phase 3a façade — yields per-state identity for missing-translation checks. ‘StateDefinition` has no DSL `label:` attribute (runtime humanizes the name), so the yield omits `label:` entirely; Pass 1 walker uses `missing_only: true` for this kind. See spec §B “Façade method signatures”.



111
112
113
114
115
116
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 111

def each_state
  return enum_for(:each_state) unless block_given?
  @states.each do |name, state|
    yield(state: name, source: state.source_loc)
  end
end

#each_state_descriptionObject

Yields per-state DSL ‘description:` literals (Tier 2 in the spec —runtime renders directly with no `state_description` lookup). Skips states without a description.



121
122
123
124
125
126
127
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 121

def each_state_description
  return enum_for(:each_state_description) unless block_given?
  @states.each do |name, state|
    next if state.description.nil?
    yield(description: state.description, state: name, source: state.description_source_loc)
  end
end

#each_transitionObject

Yields per-transition ‘label:` literals (Tier 1 — runtime `transition_label_resolver.rb:13-18` queries `lcp_ruby.workflows.<wf>.transitions.<name>` with the literal as default). Pass 1 uses `missing_only: true` here: when label is set, the literal IS the runtime fallback so override comparison is a no-op; only completeness gap matters.



135
136
137
138
139
140
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 135

def each_transition
  return enum_for(:each_transition) unless block_given?
  @transitions.each do |name, trans|
    yield(label: trans.label, transition: name, source: trans.source_loc || trans.label_source_loc)
  end
end

#has_approvals?Boolean

Returns:

  • (Boolean)


87
88
89
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 87

def has_approvals?
  @approvals.any?
end

#initial_stateObject



67
68
69
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 67

def initial_state
  @states.values.find(&:initial?)
end

#state(name) ⇒ Object



71
72
73
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 71

def state(name)
  @states[name.to_s]
end

#state_label(state_name) ⇒ Object

Returns the i18n label for a state name with humanized fallback.



99
100
101
102
103
104
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 99

def state_label(state_name)
  I18n.t(
    "lcp_ruby.workflows.#{@name}.states.#{state_name}",
    default: state_name.to_s.humanize
  )
end

#timeline_states_for_displayObject

Returns the ordered list of state names for timeline display. Uses explicit timeline_states if set, otherwise all states except those with category: rejected.



94
95
96
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 94

def timeline_states_for_display
  @timeline_states || @states.keys.reject { |k| @states[k].category == "rejected" }
end

#transition(name) ⇒ Object



75
76
77
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 75

def transition(name)
  @transitions[name.to_s]
end

#transitions_from(state_name) ⇒ Object



79
80
81
# File 'lib/lcp_ruby/workflow/workflow_definition.rb', line 79

def transitions_from(state_name)
  @transitions_by_from_state[state_name.to_s] || []
end