2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
# File 'lib/flojo.rb', line 2
def Flojo.included(host)
host.class_eval do
attr_writer :wf_current_state
attr_accessor :_wf_current_event_transition_map, :wf_previous_state
protected :wf_current_state=, :_set_workflow_state
def wf_current_state
wf_current_state = @wf_current_state.nil? ? wf_initial_state : @wf_current_state
end
if respond_to?(:after_initialize)
after_initialize :flojo_active_record_init
def flojo_active_record_init
self.wf_state = self.wf_current_state.to_s if self.respond_to?(:wf_state=)
end
end
def wf_initial_state
st = self.respond_to?(:wf_state) ? (wf_state || self.class.wf_states[0]) : self.class.wf_states[0]
st.to_sym
end
def self.workflow_states(s)
@workflow_states = s.uniq.compact
s.each do |st|
raise "Invalid Parameter. State array elements should be symbols" unless Symbol === st
end
self.synthesize_state_query_methods
end
def self.wf_states
@workflow_states
end
def self.synthesize_state_query_methods
@workflow_states.each {|st| define_method("wf_#{st}?") { st.eql?(wf_current_state)}}
end
def self.valid_states?(*states)
states.each {|st| return false if (!@workflow_states.include?(st) && (st != :any)) || !(Symbol === st)}
return true
end
end
host.class_eval("def self.transition(start_state, end_state); raise 'Invalid Transition State' unless self.valid_states?(start_state, end_state); @wf_current_event_transition_map[start_state]=end_state; end")
host.class_eval do
def self.event(e, &actions)
event_token = "wf_#{e}"
map_token = "#{event_token}_transition_map"
self.class_eval("@#{map_token}={}")
self.class_eval("def self.#{map_token}; return @#{map_token}; end")
self.class_eval("def self.wf_current_event_transition_map=(cem); @wf_current_event_transition_map=cem; end" )
self.class_eval("@wf_current_event_transition_map = @#{map_token}={}")
self.class_eval("def self.wf_current_event_transition_map; @wf_current_event_transition_map; end" )
self.class_eval("def self.wf_current_event_transition_map=(cem); @wf_current_event_transition_map=cem; end" )
self.class_eval("def #{event_token}; self._wf_current_event_transition_map=self.class.#{map_token}; _set_workflow_state \"#{e}\"; end\n")
self.class_eval("def #{event_token}!; #{event_token}; _wf_after_transition_save!; wf_after_save if self.class.method_defined? :wf_after_save; end\n" )
actions.call
end
end
end
|