Module: Workflow::Draw

Defined in:
lib/workflow/draw.rb

Class Method Summary collapse

Class Method Details

.workflow_diagram(klass, options = {}) ⇒ Object

Generates a ‘dot` graph of the workflow. Prerequisite: the `dot` binary. (Download from www.graphviz.org/) You can use this method in your own Rakefile like this:

namespace :doc do
  desc "Generate a workflow graph for a model passed e.g. as 'MODEL=Order'."
  task :workflow => :environment do
    require 'workflow/draw'
    Workflow::Draw::workflow_diagram(ENV['MODEL'].constantize)
  end
end

You can influence the placement of nodes by specifying additional meta information in your states and transition descriptions. You can assign higher ‘weight` value to the typical transitions in your workflow. All other states and transitions will be arranged around that main line. See also `weight` in the graphviz documentation. Example:

state :new do
  event :approve, :transitions_to => :approved, :meta => {:weight => 8}
end

Parameters:

  • klass

    A class with the Workflow mixin, for which you wish the graphical workflow representation

  • target_dir (String)

    Directory, where to save the dot and the pdf files

  • graph_options (String)

    You can change graph orientation, size etc. See graphviz documentation



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/workflow/draw.rb', line 43

def self.workflow_diagram(klass, options={})
  options = {
    :name => "#{klass.name.tableize}_workflow".gsub('/', '_'),
    :path => '.',
    :orientation => "landscape",
    :ratio => "fill",
    :format => 'png',
    :font => 'Helvetica'
    }.merge options

    graph = ::GraphViz.new('G', :rankdir => options[:orientation] == 'landscape' ? 'LR' : 'TB', :ratio => options[:ratio])

  # Add nodes
  klass.workflow_spec.states.each do |_, state|
    node = state.draw(graph)
    node.fontname = options[:font]

    state.events.flat.each do |event|
      edge = event.draw(graph, state)
      edge.fontname = options[:font]
    end
  end

  # Generate the graph
  filename = File.join(options[:path], "#{options[:name]}.#{options[:format]}")

  graph.output options[:format] => "'#{filename}'"

  puts "
  Please run the following to open the generated file:

  open '#{filename}'
  "
  graph
end