davidlee-state-fu 0.11.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/{state_fu/binding.rb → binding.rb} +31 -33
- data/lib/{state_fu/event.rb → event.rb} +12 -17
- data/lib/{state_fu/executioner.rb → executioner.rb} +8 -19
- data/lib/{state_fu/hooks.rb → hooks.rb} +13 -10
- data/lib/{state_fu/interface.rb → interface.rb} +0 -0
- data/lib/{state_fu/lathe.rb → lathe.rb} +12 -2
- data/lib/{state_fu/machine.rb → machine.rb} +0 -0
- data/lib/{state_fu/method_factory.rb → method_factory.rb} +0 -0
- data/lib/{state_fu/persistence.rb → persistence.rb} +0 -0
- data/lib/{state_fu/persistence → persistence}/active_record.rb +0 -0
- data/lib/{state_fu/persistence → persistence}/attribute.rb +0 -0
- data/lib/{state_fu/persistence → persistence}/base.rb +0 -0
- data/lib/{state_fu/persistence → persistence}/relaxdb.rb +0 -0
- data/lib/{state_fu/persistence → persistence}/session.rb +0 -0
- data/lib/{state_fu/sprocket.rb → sprocket.rb} +0 -0
- data/lib/state-fu.rb +11 -52
- data/lib/{state_fu/state.rb → state.rb} +0 -0
- data/lib/{state_fu → support}/active_support_lite/array.rb +0 -0
- data/lib/{state_fu → support}/active_support_lite/array/access.rb +0 -0
- data/lib/{state_fu → support}/active_support_lite/array/conversions.rb +0 -0
- data/lib/{state_fu → support}/active_support_lite/array/extract_options.rb +0 -0
- data/lib/{state_fu → support}/active_support_lite/array/grouping.rb +0 -0
- data/lib/{state_fu → support}/active_support_lite/array/random_access.rb +0 -0
- data/lib/{state_fu → support}/active_support_lite/array/wrapper.rb +0 -0
- data/lib/{state_fu → support}/active_support_lite/blank.rb +0 -0
- data/lib/{state_fu → support}/active_support_lite/cattr_reader.rb +0 -0
- data/lib/{state_fu → support}/active_support_lite/keys.rb +0 -0
- data/lib/{state_fu → support}/active_support_lite/misc.rb +0 -0
- data/lib/{state_fu → support}/active_support_lite/module.rb +0 -0
- data/lib/{state_fu → support}/active_support_lite/module/delegation.rb +0 -0
- data/lib/{state_fu → support}/active_support_lite/object.rb +0 -0
- data/lib/{state_fu → support}/active_support_lite/string.rb +0 -0
- data/lib/{state_fu → support}/active_support_lite/symbol.rb +0 -0
- data/lib/{state_fu → support}/applicable.rb +0 -0
- data/lib/{state_fu → support}/arrays.rb +0 -0
- data/lib/{state_fu → support}/core_ext.rb +1 -0
- data/lib/{state_fu → support}/exceptions.rb +0 -0
- data/lib/{state_fu → support}/has_options.rb +0 -0
- data/lib/{state_fu → support}/logger.rb +0 -0
- data/lib/{state_fu → support}/methodical.rb +0 -0
- data/lib/{no_stdout.rb → support/no_stdout.rb} +0 -0
- data/lib/{state_fu → support}/plotter.rb +1 -1
- data/lib/{vizier.rb → support/vizier.rb} +0 -0
- data/lib/{state_fu/transition.rb → transition.rb} +5 -4
- data/lib/{state_fu/transition_query.rb → transition_query.rb} +44 -67
- data/spec/integration/state_definition_spec.rb +0 -20
- data/spec/integration/transition_spec.rb +1 -1
- data/spec/state_fu_spec.rb +127 -127
- metadata +47 -48
- data/lib/state_fu.rb +0 -1
- data/lib/state_fu/nil_transition.rb +0 -49
|
@@ -58,6 +58,36 @@ module StateFu
|
|
|
58
58
|
alias_method :state_name, :current_state_name
|
|
59
59
|
alias_method :to_sym, :current_state_name
|
|
60
60
|
|
|
61
|
+
#
|
|
62
|
+
# These methods are called from methods defined by MethodFactory.
|
|
63
|
+
#
|
|
64
|
+
|
|
65
|
+
# event_name [target], *args
|
|
66
|
+
#
|
|
67
|
+
def find_transition(event, target=nil, *args)
|
|
68
|
+
target ||= args.last[:to].to_sym rescue nil
|
|
69
|
+
query = transitions.for_event(event).to(target).with(*args)
|
|
70
|
+
query.find || query.valid.singular || nil
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# event_name? [target], *args
|
|
74
|
+
#
|
|
75
|
+
def can_transition?(event, target=nil, *args)
|
|
76
|
+
begin
|
|
77
|
+
if t = find_transition(event, target, *args)
|
|
78
|
+
t.valid?(*args)
|
|
79
|
+
end
|
|
80
|
+
rescue IllegalTransition, UnknownTarget
|
|
81
|
+
nil
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# event_name! [target], *args
|
|
86
|
+
#
|
|
87
|
+
def fire_transition!(event, target=nil, *args)
|
|
88
|
+
find_transition(event, target, *args).fire!
|
|
89
|
+
end
|
|
90
|
+
|
|
61
91
|
#
|
|
62
92
|
# events
|
|
63
93
|
#
|
|
@@ -109,6 +139,7 @@ module StateFu
|
|
|
109
139
|
def transition( event_or_array, *args, &block )
|
|
110
140
|
return transitions.with(*args, &block).find(event_or_array)
|
|
111
141
|
end
|
|
142
|
+
|
|
112
143
|
#
|
|
113
144
|
# next_transition and friends: when there's exactly one valid move
|
|
114
145
|
#
|
|
@@ -248,39 +279,6 @@ module StateFu
|
|
|
248
279
|
s << ">"
|
|
249
280
|
s
|
|
250
281
|
end
|
|
251
|
-
|
|
252
|
-
# These methods are called from methods defined by MethodFactory.
|
|
253
|
-
# You probably don't want to call them directly.
|
|
254
282
|
|
|
255
|
-
# event_name
|
|
256
|
-
def find_transition(event, target=nil, *args)
|
|
257
|
-
target ||= args.last[:to].to_sym rescue nil
|
|
258
|
-
query = transitions.for_event(event).to(target).with(*args)
|
|
259
|
-
query.find || query.valid.singular || NilTransition.new
|
|
260
|
-
# transition = binding.transitions.with(*args).search([event, target])
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
# event_name?
|
|
264
|
-
def can_transition?(event, target=nil, *args)
|
|
265
|
-
begin
|
|
266
|
-
if t = find_transition(event, target, *args)
|
|
267
|
-
t.valid?(*args)
|
|
268
|
-
end
|
|
269
|
-
rescue IllegalTransition, UnknownTarget
|
|
270
|
-
nil
|
|
271
|
-
end
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
# event_name!
|
|
275
|
-
def fire_transition!(event, target=nil, *args)
|
|
276
|
-
find_transition(event, target, *args).fire!
|
|
277
|
-
end
|
|
278
|
-
|
|
279
|
-
#
|
|
280
|
-
# transition constructor
|
|
281
|
-
#
|
|
282
|
-
def new_transition(event, target, *args, &block)
|
|
283
|
-
Transition.new( self, event, target, *args, &block )
|
|
284
|
-
end
|
|
285
283
|
end
|
|
286
284
|
end
|
|
@@ -10,9 +10,11 @@ module StateFu
|
|
|
10
10
|
super( machine, name, options )
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
#
|
|
13
|
+
# Sequences: pretending events are state-local -
|
|
14
|
+
# probably a bad idea but here for a "compatibility mode"
|
|
15
|
+
# with eg the activemodel state machine
|
|
16
|
+
|
|
14
17
|
# build a hash of target => [origins]
|
|
15
|
-
#
|
|
16
18
|
def add_to_sequence origin_states, target_state
|
|
17
19
|
origin_states = [origin_states].flatten
|
|
18
20
|
existing = origin_states.select {|s| target_for_origin(s) }
|
|
@@ -23,32 +25,25 @@ module StateFu
|
|
|
23
25
|
end
|
|
24
26
|
@sequence
|
|
25
27
|
end
|
|
26
|
-
|
|
28
|
+
|
|
29
|
+
def sequence?
|
|
30
|
+
!sequence.empty?
|
|
31
|
+
end
|
|
32
|
+
|
|
27
33
|
def target_for_origin origin_state
|
|
28
34
|
raise ArgumentError.new if origin_state.nil?
|
|
29
35
|
name = sequence.detect do |k,v|
|
|
30
36
|
v.include?(origin_state.to_sym)
|
|
31
37
|
end[0] rescue nil
|
|
32
38
|
machine.states[name] if name
|
|
33
|
-
# if t
|
|
34
|
-
# puts t.inspect + " <============================" if t
|
|
35
|
-
# puts "======================"
|
|
36
|
-
# puts origin_state.class
|
|
37
|
-
# puts origin_state.name rescue origin_state.inspect
|
|
38
|
-
# end
|
|
39
|
-
# machine.states[t.first] if t
|
|
40
39
|
end
|
|
41
40
|
|
|
41
|
+
|
|
42
42
|
def can_transition_from?(origin_state)
|
|
43
43
|
( origins && origins.include?(origin_state.to_sym) && !targets.blank?) ||
|
|
44
44
|
target_for_origin(origin_state)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def sequence?
|
|
48
|
-
!sequence.empty?
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
end
|
|
46
|
+
|
|
52
47
|
# the names of all possible origin states
|
|
53
48
|
def origin_names
|
|
54
49
|
origins ? origins.map(&:to_sym) : nil
|
|
@@ -53,22 +53,12 @@ module StateFu
|
|
|
53
53
|
alias_method :arguments, :args
|
|
54
54
|
alias_method :transition_arguments, :args
|
|
55
55
|
|
|
56
|
-
# delegate :machine, :to => :binding
|
|
57
|
-
#delegate :states, :to => :machine
|
|
58
|
-
|
|
59
|
-
|
|
60
56
|
def machine
|
|
61
57
|
binding.machine
|
|
62
58
|
end
|
|
63
59
|
|
|
64
60
|
def states
|
|
65
|
-
|
|
66
|
-
# puts binding.instance_eval() { @machine }
|
|
67
|
-
# puts binding.machine
|
|
68
|
-
# puts binding.machine.states.names
|
|
69
|
-
# puts machine
|
|
70
|
-
# puts machine.states
|
|
71
|
-
# machine.states
|
|
61
|
+
machine.states
|
|
72
62
|
end
|
|
73
63
|
# delegate :machine, :to => :transition
|
|
74
64
|
|
|
@@ -137,13 +127,12 @@ module StateFu
|
|
|
137
127
|
|
|
138
128
|
end
|
|
139
129
|
|
|
140
|
-
|
|
141
|
-
#
|
|
142
|
-
#
|
|
143
|
-
#
|
|
144
|
-
#
|
|
145
|
-
#
|
|
146
|
-
#
|
|
147
|
-
#
|
|
130
|
+
# # Forwards any missing constant references to the \target.
|
|
131
|
+
# def self.const_missing(const_name)
|
|
132
|
+
# unless __target__.class.const_defined?(const_name, true)
|
|
133
|
+
# super(const_name)
|
|
134
|
+
# end
|
|
135
|
+
# __target__.class.const_get(const_name)
|
|
136
|
+
# end
|
|
148
137
|
end
|
|
149
138
|
end
|
|
@@ -20,16 +20,19 @@ module StateFu
|
|
|
20
20
|
|
|
21
21
|
# just turn the above into what each class needs
|
|
22
22
|
# and make it into a nice hash: { :name =>[ hook, ... ], ... }
|
|
23
|
-
def self.for(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
23
|
+
def self.for( instance )
|
|
24
|
+
case instance
|
|
25
|
+
when State
|
|
26
|
+
STATE_HOOKS
|
|
27
|
+
when Event
|
|
28
|
+
EVENT_HOOKS
|
|
29
|
+
when Machine
|
|
30
|
+
MACHINE_HOOKS
|
|
31
|
+
when Sprocket
|
|
32
|
+
[]
|
|
33
|
+
end.
|
|
34
|
+
map { |type, name| [name, [].extend( OrderedHash )] }.
|
|
35
|
+
to_h.extend( OrderedHash ).freeze
|
|
33
36
|
end
|
|
34
37
|
|
|
35
38
|
end
|
|
File without changes
|
|
@@ -301,7 +301,7 @@ module StateFu
|
|
|
301
301
|
|
|
302
302
|
# chain_states :a => [:b,:c], :c => :d, :c => :d
|
|
303
303
|
# chain_states :a,:b,:c,:d, :a => :c
|
|
304
|
-
def connect_states *array
|
|
304
|
+
def connect_states *array
|
|
305
305
|
array.flatten!
|
|
306
306
|
hash = array.extract_options!.symbolize_keys!
|
|
307
307
|
array.inject(nil) do |origin, target|
|
|
@@ -320,6 +320,10 @@ module StateFu
|
|
|
320
320
|
#
|
|
321
321
|
# Define a series of states at once, or return and iterate over all states yet defined
|
|
322
322
|
#
|
|
323
|
+
# states :a, :b, :c, :colour => "purple"
|
|
324
|
+
# states(:ALL) do
|
|
325
|
+
#
|
|
326
|
+
# end
|
|
323
327
|
def states *args, &block
|
|
324
328
|
valid_unless_nested()
|
|
325
329
|
each_state_or_event 'state', *args, &block
|
|
@@ -502,9 +506,15 @@ module StateFu
|
|
|
502
506
|
if args.empty? || args == [:ALL]
|
|
503
507
|
args = machine.send("#{type}s").except options.delete(:except)
|
|
504
508
|
end
|
|
509
|
+
mod = case type.to_s
|
|
510
|
+
when 'state'
|
|
511
|
+
StateArray
|
|
512
|
+
when 'event'
|
|
513
|
+
EventArray
|
|
514
|
+
end
|
|
505
515
|
args.map do |name|
|
|
506
516
|
self.send type, name, options.dup, &block
|
|
507
|
-
end.extend
|
|
517
|
+
end.extend mod
|
|
508
518
|
end
|
|
509
519
|
|
|
510
520
|
end
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
data/lib/state-fu.rb
CHANGED
|
@@ -14,61 +14,23 @@
|
|
|
14
14
|
# impose very few limits on your ability to introspect, manipulate and
|
|
15
15
|
# extend the core features.
|
|
16
16
|
#
|
|
17
|
-
# It is also delightfully elegant and easy to use for simple things
|
|
18
|
-
|
|
19
|
-
# class Document < ActiveRecord::Base
|
|
20
|
-
# include StateFu
|
|
21
|
-
#
|
|
22
|
-
# def update_rss
|
|
23
|
-
# puts "new feed!"
|
|
24
|
-
# # ... do something here
|
|
25
|
-
# end
|
|
26
|
-
#
|
|
27
|
-
# machine( :status ) do
|
|
28
|
-
# state :draft do
|
|
29
|
-
# event :publish, :to => :published
|
|
30
|
-
# end
|
|
31
|
-
#
|
|
32
|
-
# state :published do
|
|
33
|
-
# on_entry :update_rss
|
|
34
|
-
# requires :author # a database column
|
|
35
|
-
# end
|
|
36
|
-
#
|
|
37
|
-
# event :delete, :from => :ALL, :to => :deleted do
|
|
38
|
-
# execute :destroy
|
|
39
|
-
# end
|
|
40
|
-
# end
|
|
41
|
-
# end
|
|
42
|
-
#
|
|
43
|
-
# my_doc = Document.new
|
|
44
|
-
#
|
|
45
|
-
# my_doc.status # returns a StateFu::Binding, which lets us access the 'Fu
|
|
46
|
-
# my_doc.status.state => 'draft' # if this wasn't already a database column or attribute, an
|
|
47
|
-
# # attribute has been created to keep track of the state
|
|
48
|
-
# my_doc.status.name => :draft # the name of the current_state (defaults to the first defined)
|
|
49
|
-
# my_doc.status.publish! # raised => StateFu::RequirementError: [:author]
|
|
50
|
-
# # the author requirement prevented the transition
|
|
51
|
-
# my_doc.status.name => :draft # see? still a draft.
|
|
52
|
-
# my_doc.author = "Susan" # so let's satisfy it ...
|
|
53
|
-
# my_doc.publish! # and try again
|
|
54
|
-
# "new feed!" # aha - our event hook fires!
|
|
55
|
-
# my_doc.status.name => :published # and the state has been updated.
|
|
17
|
+
# It is also delightfully elegant and easy to use for simple things.
|
|
18
|
+
|
|
56
19
|
|
|
57
20
|
require 'rubygems'
|
|
58
|
-
# require 'activesupport'
|
|
59
21
|
|
|
60
|
-
[ 'core_ext',
|
|
61
|
-
'logger',
|
|
62
|
-
'applicable',
|
|
63
|
-
'arrays',
|
|
64
|
-
'methodical',
|
|
65
|
-
'has_options',
|
|
22
|
+
[ 'support/core_ext',
|
|
23
|
+
'support/logger',
|
|
24
|
+
'support/applicable',
|
|
25
|
+
'support/arrays',
|
|
26
|
+
'support/methodical',
|
|
27
|
+
'support/has_options',
|
|
28
|
+
'support/plotter',
|
|
29
|
+
'support/exceptions',
|
|
66
30
|
'executioner',
|
|
67
|
-
'exceptions',
|
|
68
31
|
'machine',
|
|
69
32
|
'lathe',
|
|
70
33
|
'method_factory',
|
|
71
|
-
'nil_transition',
|
|
72
34
|
'binding',
|
|
73
35
|
'persistence',
|
|
74
36
|
'persistence/base',
|
|
@@ -81,10 +43,7 @@ require 'rubygems'
|
|
|
81
43
|
'hooks',
|
|
82
44
|
'interface',
|
|
83
45
|
'transition',
|
|
84
|
-
'transition_query',
|
|
85
|
-
'plotter' ].each do |lib|
|
|
86
|
-
require File.expand_path( File.join( File.dirname(__FILE__), 'state_fu', lib ))
|
|
87
|
-
end
|
|
46
|
+
'transition_query' ].each { |lib| require File.expand_path(File.join(File.dirname(__FILE__),lib))}
|
|
88
47
|
|
|
89
48
|
module StateFu
|
|
90
49
|
DEFAULT = :default
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -4,6 +4,7 @@ require 'rubygems'
|
|
|
4
4
|
# some convenience methods
|
|
5
5
|
unless Object.const_defined?('ActiveSupport') #:nodoc
|
|
6
6
|
Dir[File.join(File.dirname( __FILE__), 'active_support_lite','**' )].sort.each do |lib|
|
|
7
|
+
lib = File.expand_path lib
|
|
7
8
|
next unless File.file?( lib )
|
|
8
9
|
require lib
|
|
9
10
|
end
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -23,13 +23,13 @@ module StateFu
|
|
|
23
23
|
:current_hook_slot,
|
|
24
24
|
:current_hook
|
|
25
25
|
|
|
26
|
-
alias_method :arguments, :args
|
|
26
|
+
alias_method :arguments, :args
|
|
27
27
|
|
|
28
28
|
def initialize( binding, event, target=nil, *argument_list, &block )
|
|
29
29
|
# ensure we have an Event
|
|
30
30
|
event = binding.machine.events[event] if event.is_a?(Symbol)
|
|
31
31
|
raise( UnknownTarget.new(self, "Not an event: #{event} #{self.inspect}" )) unless event.is_a? Event
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
@binding = binding
|
|
34
34
|
@machine = binding.machine
|
|
35
35
|
@object = binding.object
|
|
@@ -159,7 +159,7 @@ module StateFu
|
|
|
159
159
|
end
|
|
160
160
|
|
|
161
161
|
#
|
|
162
|
-
#
|
|
162
|
+
# Halt a transition mid-execution
|
|
163
163
|
#
|
|
164
164
|
|
|
165
165
|
# halt a transition with a message
|
|
@@ -169,7 +169,7 @@ module StateFu
|
|
|
169
169
|
end
|
|
170
170
|
|
|
171
171
|
#
|
|
172
|
-
#
|
|
172
|
+
# Fire!
|
|
173
173
|
#
|
|
174
174
|
|
|
175
175
|
# actually fire the transition
|
|
@@ -235,6 +235,7 @@ module StateFu
|
|
|
235
235
|
binding.current_state
|
|
236
236
|
end
|
|
237
237
|
|
|
238
|
+
# a little convenience for debugging / display
|
|
238
239
|
def destination
|
|
239
240
|
[event, target].map(&:to_sym)
|
|
240
241
|
end
|