class AasmStatechart::Renderer

Constants

EDGE_STYLE
END_NODE_STYLE
ENTER_CALLBACKS
EXIT_CALLBACKS
FORMATS
GRAPH_STYLE
NODE_STYLE
START_NODE_STYLE
TRANSITION_CALLBACKS

Public Class Methods

new(klass) click to toggle source
# File lib/aasm_statechart.rb, line 56
def initialize(klass)
  @start_node = nil
  @end_node = nil

  @graph = GraphViz.new(:statechart)
  @graph.type = 'digraph'

  # ruby-graphviz is missing an API to set styles in bulk, so set them here
  GRAPH_STYLE.each { |k, v| @graph.graph[k] = v }
  NODE_STYLE.each { |k, v| @graph.node[k] = v }
  EDGE_STYLE.each { |k, v| @graph.edge[k] = v }

  klass.aasm.states.each { |state| render_state(state) }
  klass.aasm.events.each { |name, event| render_event(name, event) }
end

Public Instance Methods

save(filename, format: 'png') click to toggle source
# File lib/aasm_statechart.rb, line 72
def save(filename, format: 'png')
  @graph.output({format => filename})
end

Private Instance Methods

end_node() click to toggle source
# File lib/aasm_statechart.rb, line 86
def end_node
  if @end_node.nil?
    @end_node = @graph.add_nodes(SecureRandom.uuid, **END_NODE_STYLE)
  end

  @end_node
end
get_callbacks(options, keys) click to toggle source
# File lib/aasm_statechart.rb, line 101
def get_callbacks(options, keys)
  get_options(options, keys)
    .map { |callback| "#{callback}();" }
    .join(' ')
end
get_options(options, keys) click to toggle source
# File lib/aasm_statechart.rb, line 94
def get_options(options, keys)
  options
    .select { |key| keys.include? key }
    .values
    .flatten
end
render_event(name, event) click to toggle source
# File lib/aasm_statechart.rb, line 125
def render_event(name, event)
  event.transitions.each do |transition|
    chunks = [name]

    guard = transition.options.fetch(:guard, nil)
    chunks << "[#{guard}]" if guard
    callbacks = get_callbacks(transition.options, TRANSITION_CALLBACKS)
    chunks << '/' << callbacks if callbacks.present?

    label = " #{chunks.join(' ')}  "

    @graph.add_edges(transition.from.to_s, transition.to.to_s, label: label)
  end
end
render_state(state) click to toggle source
# File lib/aasm_statechart.rb, line 107
def render_state(state)
  enter_callbacks = get_callbacks(state.options, ENTER_CALLBACKS)
  exit_callbacks = get_callbacks(state.options, EXIT_CALLBACKS)

  callbacks_list = []
  callbacks_list << "entry / #{enter_callbacks}" if enter_callbacks.present?
  callbacks_list << "exit / #{exit_callbacks}" if exit_callbacks.present?
  label = "{#{state.display_name}|#{callbacks_list.join('\l')}}"

  node = @graph.add_nodes(state.name.to_s, label: label)

  if state.options.fetch(:initial, false)
    @graph.add_edges(start_node, node)
  elsif state.options.fetch(:final, false)
    @graph.add_edges(node, end_node)
  end
end
start_node() click to toggle source
# File lib/aasm_statechart.rb, line 78
def start_node
  if @start_node.nil?
    @start_node = @graph.add_nodes(SecureRandom.uuid, **START_NODE_STYLE)
  end

  @start_node
end