Module: Workflow

Defined in:
lib/workflow.rb,
lib/workflow/version.rb

Overview

See also README.markdown for documentation

Defined Under Namespace

Modules: ActiveRecordInstanceMethods, RemodelInstanceMethods, WorkflowClassMethods, WorkflowInstanceMethods Classes: Event, NoTransitionAllowed, Specification, State, TransitionHalted, WorkflowDefinitionError, WorkflowError

Constant Summary collapse

VERSION =
"1.0.0"

Class Method Summary collapse

Class Method Details

.create_workflow_diagram(klass, target_dir = '.', graph_options = 'rankdir="LR", size="7,11.6", ratio="fill"') ⇒ 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 graph of the workflow."
  task :workflow => :environment do # needs access to the Rails environment
    Workflow::create_workflow_diagram(Order)
  end
end

You can influence the placement of nodes by specifying additional meta information in your states and transition descriptions. You can assign higher doc_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 => {:doc_weight => 8}
end

Parameters:

  • klass

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

  • target_dir (String) (defaults to: '.')

    Directory, where to save the dot and the pdf files

  • graph_options (String) (defaults to: 'rankdir="LR", size="7,11.6", ratio="fill"')

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



418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
# File 'lib/workflow.rb', line 418

def self.create_workflow_diagram(klass, target_dir='.', graph_options='rankdir="LR", size="7,11.6", ratio="fill"')
  workflow_name = "#{klass.name.tableize}_workflow".gsub('/', '_')
  fname = File.join(target_dir, "generated_#{workflow_name}")
  File.open("#{fname}.dot", 'w') do |file|
    file.puts %Q|
digraph #{workflow_name} {
graph [#{graph_options}];
node [shape=box];
edge [len=1];
    |

    klass.workflow_spec.states.each do |state_name, state|
      file.puts %Q{  #{state.name} [label="#{state.name}"];}
      state.events.each do |event_name, event|
        meta_info = event.meta
        if meta_info[:doc_weight]
          weight_prop = ", weight=#{meta_info[:doc_weight]}"
        else
          weight_prop = ''
        end
        file.puts %Q{  #{state.name} -> #{event.transitions_to} [label="#{event_name.to_s.humanize}" #{weight_prop}];}
      end
    end
    file.puts "}"
    file.puts
  end
  `dot -Tpdf -o'#{fname}.pdf' '#{fname}.dot'`
  puts "
Please run the following to open the generated file:

open '#{fname}.pdf'

"
end

.included(klass) ⇒ Object



377
378
379
380
381
382
383
384
385
386
387
388
389
390
# File 'lib/workflow.rb', line 377

def self.included(klass)
  klass.send :include, WorkflowInstanceMethods
  klass.extend WorkflowClassMethods
  if Object.const_defined?(:ActiveRecord)
    if klass < ActiveRecord::Base
      klass.send :include, ActiveRecordInstanceMethods
      klass.before_validation :write_initial_state
    end
  elsif Object.const_defined?(:Remodel)
    if klass < Remodel::Entity
      klass.send :include, RemodelInstanceMethods
    end
  end
end