Module: Apollo

Defined in:
lib/apollo.rb,
lib/apollo/event.rb,
lib/apollo/state.rb,
lib/apollo/specification.rb,
lib/apollo/active_record_instance_methods.rb

Defined Under Namespace

Modules: ActiveRecordInstanceMethods, ClassMethods, InstanceMethods Classes: ApolloDefinitionError, ApolloError, Event, NoTransitionAllowed, Specification, State, TransitionHalted

Constant Summary collapse

VERSION =

The current version

File.read(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'VERSION')).strip

Class Method Summary collapse

Class Method Details

.create_apollo_diagram(klass, target_dir, graph_options = 'rankdir="LR", size="7,11.6", ratio="fill"') ⇒ Object

Generates a ‘dot` graph of the apollo. Prerequisite: the `dot` binary. You can use it in your own Rakefile like this:

namespace :doc do
  desc "Generate a graph of the apollo."
  task :apollo do
    Apollo::create_apollo_diagram(Order.new)
  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 apollo. 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, :to => :approved, :meta => {:doc_weight => 8}
end

Parameters:

  • klass

    A class with the Apollo mixin, for which you wish the graphical apollo representation

  • target_dir (String)

    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


229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/apollo.rb', line 229

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

    klass.apollo_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.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


192
193
194
195
196
197
198
199
200
201
# File 'lib/apollo.rb', line 192

def self.included(klass)
  klass.send :include, InstanceMethods
  klass.extend ClassMethods
  if Object.const_defined?(:ActiveRecord)
    if klass < ActiveRecord::Base
    klass.send :include, ActiveRecordInstanceMethods
    klass.before_validation :write_initial_state
    end
  end
end