Permalink
Browse files

Add before_transition and after_transition hooks as suggested by kasp…

…erbn
  • Loading branch information...
1 parent 1bad6c9 commit 91498c23afb44706761d8021a8132114deb4c3d7 @geekq committed Dec 9, 2010
Showing with 80 additions and 16 deletions.
  1. +4 −0 README.markdown
  2. +40 −16 lib/workflow.rb
  3. +36 −0 test/before_transition_test.rb
View
@@ -346,11 +346,13 @@ You can check `halted?` and `halted_because` values later.
The whole event sequence is as follows:
+ * before_transition
* event specific action
* on_transition (if action did not halt)
* on_exit
* PERSIST WORKFLOW STATE, i.e. transition
* on_entry
+ * after_transition
Multiple Workflows
@@ -465,6 +467,8 @@ Changelog
* check if a certain transition possible from the current state with
`can_....?`
* fix workflow_state persistence for multiple_workflows example
+* add before_transition and after_transition hooks as suggested by
+ [kasperbn](https://github.com/kasperbn)
### New in the version 0.7.0
View
@@ -5,7 +5,8 @@ module Workflow
class Specification
- attr_accessor :states, :initial_state, :meta, :on_transition_proc
+ attr_accessor :states, :initial_state, :meta,
+ :on_transition_proc, :before_transition_proc, :after_transition_proc
def initialize(meta = {}, &specification)
@states = Hash.new
@@ -45,6 +46,14 @@ def on_exit(&proc)
@scoped_state.on_exit = proc
end
+ def after_transition(&proc)
+ @after_transition_proc = proc
+ end
+
+ def before_transition(&proc)
+ @before_transition_proc = proc
+ end
+
def on_transition(&proc)
@on_transition_proc = proc
end
@@ -159,17 +168,29 @@ def process_event!(name, *args)
if event.nil?
@halted_because = nil
@halted = false
+
+ check_transition(event)
+
+ from = current_state
+ to = spec.states[event.transitions_to]
+
+ run_before_transition(current_state, spec.states[event.transitions_to], name, *args)
+ return false if @halted
+
return_value = run_action(event.action, *args) || run_action_callback(event.name, *args)
- if @halted
- return false
- else
- check_transition(event)
- run_on_transition(current_state, spec.states[event.transitions_to], name, *args)
- transition_value = transition(
- current_state, spec.states[event.transitions_to], name, *args
- )
- return_value.nil? ? transition_value : return_value
- end
+ return false if @halted
+
+ run_on_transition(from, to, name, *args)
+
+ run_on_exit(from, to, name, *args)
+
+ transition_value = persist_workflow_state to.to_s
+
+ run_on_entry(to, from, name, *args)
+
+ run_after_transition(from, to, name, *args)
+
+ return_value.nil? ? transition_value : return_value
end
def halt(reason = nil)
@@ -210,17 +231,20 @@ def check_transition(event)
end
end
- def transition(from, to, name, *args)
- run_on_exit(from, to, name, *args)
- val = persist_workflow_state to.to_s
- run_on_entry(to, from, name, *args)
- val
+ def run_before_transition(from, to, event, *args)
+ instance_exec(from.name, to.name, event, *args, &spec.before_transition_proc) if
+ spec.before_transition_proc
end
def run_on_transition(from, to, event, *args)
instance_exec(from.name, to.name, event, *args, &spec.on_transition_proc) if spec.on_transition_proc
end
+ def run_after_transition(from, to, event, *args)
+ instance_exec(from.name, to.name, event, *args, &spec.after_transition_proc) if
+ spec.after_transition_proc
+ end
+
def run_action(action, *args)
instance_exec(*args, &action) if action
end
@@ -0,0 +1,36 @@
+require File.join(File.dirname(__FILE__), 'test_helper')
+require 'workflow'
+
+class BeforeTransitionTest < Test::Unit::TestCase
+ class MyFlow
+ attr_reader :history
+ def initialize
+ @history = []
+ end
+
+ include Workflow
+ workflow do
+ state :first do
+ event :forward, :transitions_to => :second do
+ @history << 'forward'
+ end
+ end
+ state :second do
+ event :back, :transitions_to => :first do
+ @history << 'back'
+ end
+ end
+
+ before_transition { @history << 'before' }
+ after_transition { @history << 'after' }
+ on_transition { @history << 'on' }
+ end
+ end
+
+ test 'that before_transition is run before the action' do
+ flow = MyFlow.new
+ flow.forward!
+ flow.back!
+ assert flow.history == ['before', 'forward', 'on', 'after', 'before', 'back', 'on', 'after']
+ end
+end

0 comments on commit 91498c2

Please sign in to comment.