Skip to content

Commit

Permalink
PR-241 Defining workflow dynamically from JSON
Browse files Browse the repository at this point in the history
  • Loading branch information
geekq committed May 29, 2024
1 parent 5e6849a commit 2869e4f
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 0 deletions.
7 changes: 7 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,12 @@ The workflow library itself uses this feature to tweak the graphical
representation of the workflow. See below.
### Defining workflow dynamically from JSON
For an advance example please see
link:https://github.com/geekq/workflow/blob/develop/test/workflow_from_json_test.rb[workflow_from_json_test.rb].
### Compose workflow definition with `include`
In case you have very extensive workflow definition or would like to reuse
Expand Down Expand Up @@ -525,6 +531,7 @@ Changelog
* link:https://github.com/geekq/workflow/pull/227[#227] Allow event arguments to be taken into account when selecting the event
* link:https://github.com/geekq/workflow/pull/232[#232] Add ability to include partial workflow definitions for composability
* link:https://github.com/geekq/workflow/pull/241[#241] Example for defining workflow dynamically from JSON
=== New in the version 3.0.0
Expand Down
158 changes: 158 additions & 0 deletions test/workflow_from_json_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
require File.join(File.dirname(__FILE__), 'test_helper')
require 'workflow'
class WorkflowFromJsonTest < Minitest::Test

test '#241 define a workflow from JSON' do
c = Class.new
c.class_eval do
include Workflow

attr_reader :events

def record(event)
@events ||= []
@events << event
end

def ran?(event)
@events.include? event
end

def clear_events
@events = []
end

def event_1(test)
# puts "running event_1 with arg '#{test}'"
record __method__
end

def before_transition(from, to, triggering_event, *args, **kwargs)
# puts "before_transition #{from} -> #{to}, #{triggering_event}, #{args}, #{kwargs}"
record __method__
end

def on_transition(from, to, triggering_event, *args, **kwargs)
# puts "on_transition #{from} -> #{to}, #{triggering_event}, #{args}, #{kwargs}"
record __method__
end

def after_transition(from, to, triggering_event, *args, **kwargs)
# puts "after_transition #{from} -> #{to}, #{triggering_event}, #{args}, #{kwargs}"
record __method__
end

def event_1_condition?
# puts "event_1_condition? -> true"
record __method__
true
end

def on_state_1_exit(new_state, event, *args)
# puts "on_state_1_exit(#{new_state}, #{event}, #{args})"
record __method__
end

def entering_state_2(prior_state, triggering_event, *args, **kwargs)
# puts "entering_state_2 #{prior_state}, #{triggering_event}, #{args}, #{kwargs}"
record __method__
end

def entering_state_3(prior_state, triggering_event, *args, **kwargs)
# puts "entering_state_3 #{prior_state}, #{triggering_event}, #{args}, #{kwargs}"
record __method__
end

def on_state_2_entry(new_state, event, *args)
# puts "on_state_2_entry(#{new_state}, #{event}, #{args})"
record __method__
end

end

ran_normal = []
hash = {
state_1: {
events: {
event_1: {
transition_to: :state_2,
if: :event_1_condition?,
meta: { e1: 1 }
},
},
meta: { a: 1 }
},
state_2: {
events: {
event_2: {
transition_to: :state_3,
}
},
on_entry: :entering_state_2,
meta: { a: 2 }
},
state_3: {
on_entry: "entering_state_3",
}
}

spec = Workflow::Specification.new do

hash.each_pair do |state_name, state_def|

state state_name, state_def

on_entry {|prior_state, triggering_event| send state_def[:on_entry], prior_state, triggering_event } if state_def.include?(:on_entry)
on_exit { ran_normal << :on_exit }

state_def[:events]&.each_pair do |event_name, event_def|
event event_name, event_def
end

end

before_transition do |from, to, triggering_event, *args, **kwargs|
ran_normal << :before_transition
before_transition(from, to, triggering_event, *args, **kwargs)
end

on_transition do |from, to, triggering_event, *args, **kwargs|
ran_normal << :on_transition
on_transition(from, to, triggering_event, *args, **kwargs)
end

after_transition do |from, to, triggering_event, *args, **kwargs|
ran_normal << :after_transition
after_transition(from, to, triggering_event, *args, **kwargs)
end

end

c.send :assign_workflow, spec

o = c.new

assert o.state_1?, "Should be state_1"
refute o.state_2?, "Should not be state_2"

o.event_1! "hello"
[:event_1_condition?, :event_1, :entering_state_2, :before_transition, :on_transition, :after_transition].each do |event|
assert o.ran?(event), "Should have run event #{event}"
end

refute o.state_1?, "Should not be state_1"
assert o.state_2?, "Should be state_2"

o.clear_events
o.event_2!
refute o.ran?(:event_1), "Should not have run event_1"
[:entering_state_3, :before_transition, :on_transition, :after_transition].each do |event|
assert o.ran?(event), "Should have run event #{event}"
end

assert ran_normal.include?(:before_transition), "Should have run before_transition proc"
assert ran_normal.include?(:on_transition), "Should have run on_transition proc"
assert ran_normal.include?(:after_transition), "Should have run after_transition proc"
assert ran_normal.include?(:on_exit), "Should have run on_exit proc"
end
end

0 comments on commit 2869e4f

Please sign in to comment.