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.
Files changed (51) hide show
  1. data/lib/{state_fu/binding.rb → binding.rb} +31 -33
  2. data/lib/{state_fu/event.rb → event.rb} +12 -17
  3. data/lib/{state_fu/executioner.rb → executioner.rb} +8 -19
  4. data/lib/{state_fu/hooks.rb → hooks.rb} +13 -10
  5. data/lib/{state_fu/interface.rb → interface.rb} +0 -0
  6. data/lib/{state_fu/lathe.rb → lathe.rb} +12 -2
  7. data/lib/{state_fu/machine.rb → machine.rb} +0 -0
  8. data/lib/{state_fu/method_factory.rb → method_factory.rb} +0 -0
  9. data/lib/{state_fu/persistence.rb → persistence.rb} +0 -0
  10. data/lib/{state_fu/persistence → persistence}/active_record.rb +0 -0
  11. data/lib/{state_fu/persistence → persistence}/attribute.rb +0 -0
  12. data/lib/{state_fu/persistence → persistence}/base.rb +0 -0
  13. data/lib/{state_fu/persistence → persistence}/relaxdb.rb +0 -0
  14. data/lib/{state_fu/persistence → persistence}/session.rb +0 -0
  15. data/lib/{state_fu/sprocket.rb → sprocket.rb} +0 -0
  16. data/lib/state-fu.rb +11 -52
  17. data/lib/{state_fu/state.rb → state.rb} +0 -0
  18. data/lib/{state_fu → support}/active_support_lite/array.rb +0 -0
  19. data/lib/{state_fu → support}/active_support_lite/array/access.rb +0 -0
  20. data/lib/{state_fu → support}/active_support_lite/array/conversions.rb +0 -0
  21. data/lib/{state_fu → support}/active_support_lite/array/extract_options.rb +0 -0
  22. data/lib/{state_fu → support}/active_support_lite/array/grouping.rb +0 -0
  23. data/lib/{state_fu → support}/active_support_lite/array/random_access.rb +0 -0
  24. data/lib/{state_fu → support}/active_support_lite/array/wrapper.rb +0 -0
  25. data/lib/{state_fu → support}/active_support_lite/blank.rb +0 -0
  26. data/lib/{state_fu → support}/active_support_lite/cattr_reader.rb +0 -0
  27. data/lib/{state_fu → support}/active_support_lite/keys.rb +0 -0
  28. data/lib/{state_fu → support}/active_support_lite/misc.rb +0 -0
  29. data/lib/{state_fu → support}/active_support_lite/module.rb +0 -0
  30. data/lib/{state_fu → support}/active_support_lite/module/delegation.rb +0 -0
  31. data/lib/{state_fu → support}/active_support_lite/object.rb +0 -0
  32. data/lib/{state_fu → support}/active_support_lite/string.rb +0 -0
  33. data/lib/{state_fu → support}/active_support_lite/symbol.rb +0 -0
  34. data/lib/{state_fu → support}/applicable.rb +0 -0
  35. data/lib/{state_fu → support}/arrays.rb +0 -0
  36. data/lib/{state_fu → support}/core_ext.rb +1 -0
  37. data/lib/{state_fu → support}/exceptions.rb +0 -0
  38. data/lib/{state_fu → support}/has_options.rb +0 -0
  39. data/lib/{state_fu → support}/logger.rb +0 -0
  40. data/lib/{state_fu → support}/methodical.rb +0 -0
  41. data/lib/{no_stdout.rb → support/no_stdout.rb} +0 -0
  42. data/lib/{state_fu → support}/plotter.rb +1 -1
  43. data/lib/{vizier.rb → support/vizier.rb} +0 -0
  44. data/lib/{state_fu/transition.rb → transition.rb} +5 -4
  45. data/lib/{state_fu/transition_query.rb → transition_query.rb} +44 -67
  46. data/spec/integration/state_definition_spec.rb +0 -20
  47. data/spec/integration/transition_spec.rb +1 -1
  48. data/spec/state_fu_spec.rb +127 -127
  49. metadata +47 -48
  50. data/lib/state_fu.rb +0 -1
  51. 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
- # puts binding
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
- # # Forwards any missing method call to the \target.
141
- # def self.const_missing(const_name)
142
- # unless __target__.class.const_defined?(const_name, true)
143
- # super(const_name)
144
- # end
145
- # __target__.class.const_get(const_name)
146
- # end
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( me )
24
- x = if me.is_a?(State); STATE_HOOKS
25
- elsif me.is_a?(Event); EVENT_HOOKS
26
- elsif me.is_a?(Machine); MACHINE_HOOKS
27
- elsif me.is_a?(Sprocket); [] # let specs pass
28
- else raise me
29
- end.
30
- map { |type, name| [name, [].extend( OrderedHash )] }
31
- hash = x.inject({}) {|h, a| h[a.first] = a.last; h }
32
- hash.extend( OrderedHash ).freeze
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, &b
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 ArrayWithSymbolAccessor
517
+ end.extend mod
508
518
  end
509
519
 
510
520
  end
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
@@ -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
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__),'../vizier')
1
+ require 'vizier'
2
2
  require 'tempfile'
3
3
 
4
4
  module StateFu
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