lib/workflow/draw.rb
module Workflow
module Draw
# Generates a `dot` graph of the workflow.
# Prerequisite: the `dot` binary. (Download from http://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
#
#
# @param klass A class with the Workflow mixin, for which you wish the graphical workflow representation
# @param [String] target_dir Directory, where to save the dot and the pdf files
# @param [String] graph_options You can change graph orientation, size etc. See graphviz documentation
def self.workflow_diagram(klass, options={})
# TODO: find some replacement for ActiveSupport::Inflector.tableize
# or make it usage optional
options = {
# :name => "#{klass.name.tableize}_workflow".gsub('/', '_'),
:name => "#{klass.name}_workflow".gsub('/', '_'),
:path => '.',
:orientation => "landscape",
:ratio => "fill",
:format => 'png',
:font => 'Helvetica'
}.merge options
require 'ruby-graphviz'
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
end
end