davidlee-state-fu 0.10.0 → 0.11.0

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.rb CHANGED
@@ -68,6 +68,7 @@ require 'rubygems'
68
68
  'machine',
69
69
  'lathe',
70
70
  'method_factory',
71
+ 'nil_transition',
71
72
  'binding',
72
73
  'persistence',
73
74
  'persistence/base',
@@ -27,10 +27,10 @@ module StateFu
27
27
  @machine.helpers.inject_into( self )
28
28
  end
29
29
 
30
- alias_method :o, :object
31
- alias_method :obj, :object
32
- alias_method :model, :object
33
- alias_method :instance, :object
30
+ alias_method :o, :object
31
+ alias_method :obj, :object
32
+ alias_method :model, :object
33
+ alias_method :instance, :object
34
34
 
35
35
  alias_method :workflow, :machine
36
36
  alias_method :state_machine, :machine
@@ -70,12 +70,6 @@ module StateFu
70
70
  end
71
71
  alias_method :events_from_current_state, :events
72
72
 
73
- # the subset of events() whose requirements for firing are NOT met
74
- # (with the arguments supplied, if any)
75
- def invalid_events( *args )
76
- ( events - valid_events( *args ) ).extend StateArray
77
- end
78
-
79
73
  # all states which can be reached from the current_state.
80
74
  # Does not check transition requirements, etc.
81
75
  def next_states
@@ -95,12 +89,17 @@ module StateFu
95
89
  end
96
90
 
97
91
  def valid_next_states(*args)
98
- transitions.with(*args).targets
92
+ valid_transitions(*args).targets
99
93
  end
100
94
 
101
95
  def valid_events(*args)
102
- transitions.with(*args).events
96
+ valid_transitions(*args).events
97
+ end
98
+
99
+ def invalid_events(*args)
100
+ (events - valid_events(*args)).extend StateArray
103
101
  end
102
+
104
103
 
105
104
  # initializes a new Transition to the given destination, with the
106
105
  # given *args (to be passed to requirements and hooks).
@@ -110,33 +109,6 @@ module StateFu
110
109
  def transition( event_or_array, *args, &block )
111
110
  return transitions.with(*args, &block).find(event_or_array)
112
111
  end
113
- alias_method :fire, :transition
114
- alias_method :fire_event, :transition
115
- alias_method :trigger, :transition
116
- alias_method :trigger_event, :transition
117
- alias_method :begin_transition, :transition
118
-
119
- # check that the event and target are valid (all requirements are
120
- # met) with the given (optional) arguments
121
- def fireable?( event_or_array, *args )
122
- begin
123
- return nil unless t = transition( event_or_array, *args )
124
- !! t.requirements_met?
125
- rescue InvalidTransition => e
126
- nil
127
- end
128
- end
129
-
130
- # construct an event transition and fire it, returning the transition.
131
- # (which is == true if the transition completed successfully.)
132
- def fire!( event_or_array, *args, &block)
133
- # TODO rather than die, try to find the next valid transition and fire that
134
- t = transition(event_or_array, *args, &block )
135
- t.fire!
136
- end
137
- alias_method :trigger!, :fire!
138
- alias_method :transition!, :fire!
139
-
140
112
  #
141
113
  # next_transition and friends: when there's exactly one valid move
142
114
  #
@@ -155,7 +127,7 @@ module StateFu
155
127
  # if there is exactly one state reachable via a transition which
156
128
  # is valid with the given optional arguments, return it.
157
129
  def next_state(*args, &block)
158
- transitions.with(*args, &block).next_state
130
+ transitions.with(*args, &block).next_state
159
131
  end
160
132
 
161
133
  # if there is exactly one event which is valid with the given
@@ -165,7 +137,7 @@ module StateFu
165
137
  end
166
138
 
167
139
  # if there is a next_transition, create, fire & return it
168
- # otherwise raise an InvalidTransition
140
+ # otherwise raise an IllegalTransition
169
141
  def next!( *args, &block )
170
142
  if t = next_transition( *args, &block )
171
143
  t.fire!
@@ -176,7 +148,7 @@ module StateFu
176
148
  alias_method :next_transition!, :next!
177
149
  alias_method :next_event!, :next!
178
150
  alias_method :next_state!, :next!
179
-
151
+
180
152
  # if there is a next_transition, return true / false depending on
181
153
  # whether its requirements are met
182
154
  # otherwise, nil
@@ -202,13 +174,12 @@ module StateFu
202
174
  end
203
175
 
204
176
  # if there is a single possible cycle() transition, fire and return it
205
- # otherwise raise an InvalidTransition
177
+ # otherwise raise an IllegalTransition
206
178
  def cycle!(event_or_array=nil, *args, &block )
207
- if t = cycle(event_or_array, *args, &block )
179
+ returning cycle(event_or_array, *args, &block ) do |t|
180
+ raise TransitionNotFound.new( self, transitions.cyclic.with(*args,&block), "Cannot cycle! unless there is exactly one cyclic event") \
181
+ if t.nil?
208
182
  t.fire!
209
- t
210
- else
211
- raise TransitionNotFound.new( self, transitions.cyclic.with(*args,&block), "Cannot cycle! unless there is exactly one cyclic event")
212
183
  end
213
184
  end
214
185
 
@@ -233,13 +204,13 @@ module StateFu
233
204
 
234
205
  # display something sensible that doesn't take up the whole screen
235
206
  def inspect
236
- '|<= ' + self.class.to_s + ' ' +
207
+ '<#' + self.class.to_s + ' ' +
237
208
  attrs = [[:current_state, state_name.inspect],
238
209
  [:object_type , @object.class],
239
210
  [:method_name , method_name.inspect],
240
211
  [:field_name , field_name.inspect],
241
- [:machine , machine.inspect]].
242
- map {|x| x.join('=') }.join( " " ) + ' =>|'
212
+ [:machine , machine.to_s]].
213
+ map {|x| x.join('=') }.join( " " ) + '>'
243
214
  end
244
215
 
245
216
  # let's be == (and hence ===) the current_state_name as a symbol.
@@ -267,31 +238,42 @@ module StateFu
267
238
  self
268
239
  end
269
240
 
270
- # This method is called from methods defined by MethodFactory.
271
- # You don't want to call it directly.
272
- def _event_method(action, event, *args)
273
- target_or_options = args.shift
274
- options = {}
275
- case target_or_options
276
- when Hash
277
- options = target_or_options.symbolize_keys!
278
- target = target_or_options.delete[:to]
279
- when Symbol, String
280
- target = target_or_options.to_sym
281
- when nil
282
- target = nil
283
- end
241
+ def inspect
242
+ s = self.to_s
243
+ s = s[0,s.length-1]
244
+ s << " object=#{object}"
245
+ s << " current_state=#{current_state.to_sym.inspect rescue nil}"
246
+ s << " events=#{events.map(&:to_sym).inspect rescue nil}"
247
+ s << " machine=#{machine.to_s}"
248
+ s << ">"
249
+ s
250
+ end
284
251
 
285
- case action
286
- when :get_transition
287
- transition [event, target], *args, &lambda {|t| t.options = options}
288
- when :query_transition
289
- fireable? [event, target], *args, &lambda {|t| t.options = options}
290
- when :fire_transition
291
- fire! [event, target], *args, &lambda {|t| t.options = options}
292
- else
293
- raise ArgumentError.new(action)
294
- end
252
+ # These methods are called from methods defined by MethodFactory.
253
+ # You probably don't want to call them directly.
254
+
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!
295
277
  end
296
278
 
297
279
  #
@@ -92,14 +92,15 @@ module StateFu
92
92
  class TransitionHalted < TransitionError
93
93
  end
94
94
 
95
- class InvalidTransition < TransitionError
96
- attr_reader :valid_transitions
95
+ # deprecated?
96
+ # class Invalid Transition < TransitionError
97
+
98
+ class IllegalTransition < TransitionError
99
+ attr_reader :legal_transitions
97
100
 
98
101
  def initialize transition, message=nil, valid_transitions=nil, options={}
99
102
  @valid_transitions = valid_transitions
100
103
  super transition, message, options
101
- end
102
-
104
+ end
103
105
  end
104
-
105
106
  end
@@ -6,63 +6,103 @@ module StateFu
6
6
  # complex events will be called as: event_name! :state, *args
7
7
 
8
8
  class MethodFactory
9
-
9
+ attr_accessor :method_definitions
10
+ attr_reader :binding
11
+
10
12
  # An instance of MethodFactory is created to define methods on a specific StateFu::Binding, and
11
- # the object it is bound to.
12
- #
13
- # During the initializer, it will call define_event_methods_on(the binding), which installs
14
- #
13
+ # on the object it is bound to.
14
+
15
15
  def initialize( _binding )
16
- # store @binding in a local variable so it's accessible within
17
- # the closures below (for define_singleton_method ).
16
+ @binding = _binding
17
+ simple_events, complex_events = @binding.machine.events.partition(&:simple?)
18
+ @method_definitions = {}
19
+
20
+ # simple event methods
21
+ # all arguments are passed into the transition / transition query
22
+
23
+ simple_events.each do |event|
24
+ method_definitions["#{event.name}"] = lambda do |*args|
25
+ _binding.find_transition(event, event.target, *args)
26
+ end
27
+
28
+ method_definitions["can_#{event.name}?"] = lambda do |*args|
29
+ _binding.can_transition?(event, event.target, *args)
30
+ end
31
+
32
+ method_definitions["#{event.name}!"] = lambda do |*args|
33
+ _binding.fire_transition!(event, event.target, *args)
34
+ end
35
+ end
36
+
37
+ # complex event methods
38
+ # the first argument is the target state
39
+ # any remaining arguments are passed into the transition / transition query
40
+
41
+ # object.event_name [:target], *arguments
42
+ #
43
+ # returns a new transition. Will raise an IllegalTransition if
44
+ # it is not given arguments which result in a valid combination
45
+ # of event and target state being deducted.
46
+ #
47
+ # object.event_name [nil] suffices if the event has only one valid
48
+ # target (ie only one transition which would not raise a
49
+ # RequirementError if fired)
50
+
51
+ # object.event_name! [:target], *arguments
52
+ #
53
+ # as per the method above, except that it also fires the event
54
+
55
+ # object.can_event_name? [:target], *arguments
56
+ #
57
+ # tests that calling event_name or event_name! would not raise an error
58
+ # ie, the transition is legal and is valid with the arguments supplied
59
+
60
+ complex_events.each do |event|
61
+ method_definitions["#{event.name}"] = lambda do |target, *args|
62
+ _binding.find_transition(event, target, *args)
63
+ end
64
+
65
+ method_definitions["can_#{event.name}?"] = lambda do |target, *args|
66
+ begin
67
+ t = _binding.find_transition(event, target, *args)
68
+ t.valid?
69
+ rescue IllegalTransition
70
+ false
71
+ end
72
+ end
18
73
 
19
- # i.e, we're embedding a reference to @binding inside the method
20
- @binding = _binding
21
- @defs = {}
74
+ method_definitions["#{event.name}!"] = lambda do |target, *args|
75
+ _binding.fire_transition!(event, target, *args)
76
+ end
77
+ end
78
+
79
+ # methods dedicated to a combination of event and target
80
+ # all arguments are passed into the transition / transition query
81
+
82
+ (simple_events + complex_events).each do |event|
83
+ event.targets.each do |target|
84
+ method_definitions["#{event.name}_to_#{target.name}"] = lambda do |*args|
85
+ _binding.find_transition(event, target, *args)
86
+ end
87
+
88
+ method_definitions["can_#{event.name}_to_#{target.name}?"] = lambda do |*args|
89
+ _binding.can_transition?(event, target, *args)
90
+ end
22
91
 
92
+ method_definitions["#{event.name}_to_#{target.name}!"] = lambda do |*args|
93
+ _binding.fire_transition!(event, target, *args)
94
+ end
95
+ end unless event.targets.nil?
96
+ end
97
+
23
98
  @binding.machine.states.each do |state|
24
- @defs[:"#{state.name}?"] = lambda { _binding.current_state.name == state.name }
99
+ method_definitions["#{state.name}?"] = lambda do
100
+ _binding.current_state == state
101
+ end
25
102
  end
26
103
 
27
- # method definitions for simple events (only one possible target)
28
- @binding.machine.events.each do |event|
29
- @defs[event.name] = lambda \
30
- {|*args| _binding._event_method :get_transition, event, args.shift, *args }
31
- @defs[:"can_#{event.name}?"] = lambda \
32
- {|*args| _binding._event_method :query_transition, event, args.shift, *args }
33
- @defs[:"#{event.name}!"] = lambda \
34
- {|*args| _binding._event_method :fire_transition, event, args.shift, *args }
35
-
36
- #if !event.targets.blank? # && event.targets.length > 1
37
- event.targets.each do |target_state|
38
- method_name = "#{event.name}_to_#{target_state.name}"
39
-
40
- # object.event_name [:target], *arguments
41
- #
42
- # returns a new transition. Will raise an InvalidTransition if
43
- # it is not given arguments which result in a valid combination
44
- # of event and target state being deducted.
45
- #
46
- # object.event_name suffices without any arguments if the event
47
- # has only one possible target, or only one valid target for
104
+ end
48
105
 
49
- # object.event_name! [:target], *arguments
50
- #
51
- # as per the method above, except that it also
52
-
53
- @defs[method_name.to_sym] = lambda \
54
- {|*args| _binding._event_method :get_transition, event, target_state, *args }
55
-
56
- # object.event_name! [:]
57
- @defs[:"can_#{method_name}?"] = lambda \
58
- {|*args| _binding._event_method :query_transition, event, target_state, *args }
59
-
60
- @defs[:"#{method_name}!"] = lambda \
61
- {|*args| _binding._event_method :fire_transition, event, target_state, *args }
62
-
63
- end unless event.targets.nil?
64
- end
65
- end
66
106
 
67
107
  #
68
108
  # Class Methods
@@ -163,7 +203,7 @@ module StateFu
163
203
  # as with simple event methods.
164
204
  #
165
205
  def define_event_methods_on( obj )
166
- @defs.each do |method_name, method_body|
206
+ method_definitions.each do |method_name, method_body|
167
207
  define_singleton_method( obj, method_name, &method_body)
168
208
  end
169
209
  end # define_event_methods_on
@@ -196,7 +236,7 @@ module StateFu
196
236
  end
197
237
  end
198
238
  alias_method :define_singleton_method, :define_singleton_method
199
-
239
+
200
240
  end # class MethodFactory
201
241
  end # module StateFu
202
242
 
@@ -0,0 +1,49 @@
1
+ module StateFu
2
+
3
+ class NilTransition
4
+ def method_missing(method_name, *args, &block)
5
+ nil
6
+ end
7
+
8
+ def blank?
9
+ true
10
+ end
11
+
12
+ def nil?
13
+ true
14
+ end
15
+
16
+ # def <=> x
17
+ # false <=> x
18
+ # end
19
+ #
20
+ # def | x
21
+ # false
22
+ # end
23
+ #
24
+ # def & x
25
+ # false
26
+ # end
27
+ #
28
+ # def ^ x
29
+ # false
30
+ # end
31
+ #
32
+ # def equal? x
33
+ # x.is_a? NilTransition || x == nil
34
+ # end
35
+
36
+ def == x
37
+ case x
38
+ when false
39
+ true
40
+ when true
41
+ false
42
+ else
43
+ nil
44
+ end
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -23,57 +23,67 @@ module StateFu
23
23
  :current_hook_slot,
24
24
  :current_hook
25
25
 
26
- attr_accessor :test_only
27
26
  alias_method :arguments, :args
28
27
 
29
28
  def initialize( binding, event, target=nil, *argument_list, &block )
30
- # ensure event is a StateFu::Event
31
- if event.is_a?(Symbol) && e = binding.machine.events[event]
32
- event = e
33
- end
34
- raise( ArgumentError, "Not an event: #{event}" ) unless event.is_a? Event
29
+ # ensure we have an Event
30
+ event = binding.machine.events[event] if event.is_a?(Symbol)
31
+ raise( UnknownTarget.new(self, "Not an event: #{event} #{self.inspect}" )) unless event.is_a? Event
35
32
 
36
33
  @binding = binding
37
34
  @machine = binding.machine
38
35
  @object = binding.object
39
36
  @origin = binding.current_state
40
37
 
41
- self.args= argument_list
42
- apply!(argument_list, &block )
43
-
44
38
  # ensure we have a target
45
39
  target = find_event_target( event, target ) || raise( UnknownTarget.new(self, "target cannot be determined: #{target.inspect} #{self.inspect}"))
46
40
 
47
41
  @target = target
48
42
  @event = event
49
43
  @errors = []
50
- @testing = @options.delete(:test_only)
51
44
 
52
45
  if event.target_for_origin(origin) == target
53
- # ...
46
+ # it's a "sequence"
47
+ # which is a hacky way of emulating simpler state machines with
48
+ # state-local events - and in which case, the targets & origins are
49
+ # valid. Quite likely this notion will be removed in time.
54
50
  else
55
51
  # ensure target is valid for the event
56
52
  unless event.targets.include? target
57
- raise InvalidTransition.new self, "Illegal target #{target} for #{event}"
53
+ raise IllegalTransition.new self, "Illegal target #{target} for #{event}"
58
54
  end
59
55
 
60
56
  # ensure current_state is a valid origin for the event
61
57
  unless event.origins.include? origin
62
- raise InvalidTransition.new( self, "Illegal event #{event.name} for current state #{binding.state_name}" )
58
+ raise IllegalTransition.new( self, "Illegal event #{event.name} for current state #{binding.state_name}" )
63
59
  end
64
60
  end
65
61
 
66
62
  machine.inject_helpers_into( self )
63
+ self.args = argument_list
64
+ apply!(argument_list, &block )
67
65
  end
68
-
69
- def options=(opts={})
70
- @options = opts
66
+
67
+
68
+ def valid?(*args)
69
+ self.args = args unless args.empty?
70
+ requirements_met?(true, true) # revalidate; exit on first failure
71
+ end
72
+
73
+ def args=(args)
74
+ @args = args.extend(TransitionArgsArray).init(self)
75
+ apply!(args) if args.last.is_a?(Hash) unless options.nil?
76
+ end
77
+
78
+ def with(*args)
79
+ self.args = args unless args.empty?
80
+ self
71
81
  end
72
82
 
73
- def args=(a)
74
- @args = a.extend(TransitionArgsArray).init(self)
75
- apply!(a) if a.last.is_a?(Hash)
83
+ def with?(*args)
84
+ valid?
76
85
  end
86
+ alias_method :valid_with?, :with?
77
87
 
78
88
  #
79
89
  # Requirements
@@ -83,18 +93,20 @@ module StateFu
83
93
  origin.exit_requirements + target.entry_requirements + event.requirements
84
94
  end
85
95
 
86
- def unmet_requirements(revalidate=false, fail_fast=false) # TODO
96
+ def unmet_requirements(revalidate=false, fail_fast=false)
87
97
  if revalidate
88
- return @unmet_requirements if @unmet_requirements
89
- else
90
98
  @unmet_requirements = nil
99
+ else
100
+ return @unmet_requirements if @unmet_requirements
91
101
  end
92
- result = requirements.uniq.inject([]) do |unmet, requirement|
93
- next if fail_fast && !unmet.empty?
102
+ result = [requirements].flatten.uniq.inject([]) do |unmet, requirement|
94
103
  unmet << requirement unless evaluate(requirement)
104
+ break(unmet) if fail_fast && !unmet.empty?
95
105
  unmet
96
106
  end
97
- @unmet_requirements = result if (!fail_fast || unmet_requirements.length <= 1)
107
+ raise self.inspect if result.nil?
108
+ # don't cache result if it might
109
+ @unmet_requirements = result unless (fail_fast && unmet_requirements.length != 0)
98
110
  result
99
111
  end
100
112
 
@@ -104,25 +116,23 @@ module StateFu
104
116
 
105
117
  def unmet_requirement_messages(revalidate=false, fail_fast=false) # TODO
106
118
  unmet_requirements(revalidate, fail_fast).map do |requirement|
107
- evaluate_requirement_message requirement
119
+ evaluate_requirement_message(requirement, revalidate)
108
120
  end.extend MessageArray
109
121
  end
110
122
  alias_method :error_messages, :unmet_requirement_messages
111
-
123
+
124
+ # return a hash of requirement_name => evaluated message
112
125
  def requirement_errors(revalidate=false, fail_fast=false)
113
126
  unmet_requirements(revalidate, fail_fast).
114
127
  map { |requirement| [requirement, evaluate_requirement_message(requirement)]}.
115
128
  to_h
116
129
  end
117
-
118
- def first_unmet_requirement(revalidate=false)
119
- unmet_requirements(revalidate, fail_fast=true)[0]
120
- end
121
-
130
+
122
131
  def first_unmet_requirement_message(revalidate=false)
123
- unmet_requirement_messages(revalidate, fail_fast=true)[0]
132
+ evaluate_requirement_message(first_unmet_requirement(revalidate), revalidate)
124
133
  end
125
134
 
135
+ # raise a RequirementError unless all requirements are met.
126
136
  def check_requirements!(revalidate=false, fail_fast=true) # TODO
127
137
  raise RequirementError.new( self, unmet_requirement_messages.inspect ) unless requirements_met?(revalidate, fail_fast)
128
138
  end
@@ -130,7 +140,6 @@ module StateFu
130
140
  def requirements_met?(revalidate=false, fail_fast=false) # TODO
131
141
  unmet_requirements(revalidate, fail_fast).empty?
132
142
  end
133
- alias_method :valid?, :requirements_met?
134
143
 
135
144
  #
136
145
  # Hooks
@@ -149,8 +158,6 @@ module StateFu
149
158
  evaluate hook
150
159
  end
151
160
 
152
-
153
-
154
161
  #
155
162
  #
156
163
  #
@@ -166,9 +173,10 @@ module StateFu
166
173
  #
167
174
 
168
175
  # actually fire the transition
169
- def fire!
176
+ def fire!(*arguments) # block?
170
177
  raise TransitionAlreadyFired.new(self) if fired?
171
- # return false if fired? # no infinite loops please
178
+ self.args = arguments unless arguments.empty?
179
+
172
180
  check_requirements!
173
181
  @fired = true
174
182
  begin
@@ -218,14 +226,6 @@ module StateFu
218
226
  !!@fired
219
227
  end
220
228
 
221
- def testing?
222
- !!@test_only
223
- end
224
-
225
- def live?
226
- !testing?
227
- end
228
-
229
229
  def accepted?
230
230
  !!@accepted
231
231
  end
@@ -256,12 +256,6 @@ module StateFu
256
256
  alias_method :initial_state, :origin
257
257
  alias_method :from, :origin
258
258
 
259
- alias_method :test?, :testing?
260
- alias_method :test_only?, :testing?
261
- alias_method :read_only?, :testing?
262
- alias_method :only_pretend?, :testing?
263
- alias_method :dry_run?, :testing?
264
-
265
259
  # an accepted transition == true
266
260
  # an unaccepted transition == false
267
261
  # same for === (for case equality)
@@ -306,26 +300,28 @@ module StateFu
306
300
  executioner.evaluate(method_name_or_proc)
307
301
  end
308
302
 
309
- def evaluate_requirement_message( name )
310
- msg = machine.requirement_messages[name]
311
- case msg
312
- when String
313
- msg
314
- when nil
315
- name
316
- when Symbol, Proc
317
- evaluate msg
318
- else
319
- raise msg.class.to_s
320
- end
303
+ def evaluate_requirement_message( name, revalidate=false)
304
+ @requirement_messages ||= {}
305
+ name = name.to_sym
306
+ return @requirement_messages[name] if @requirement_messages[name] && !revalidate
307
+ msg = machine.requirement_messages[name.to_sym]
308
+ result = case msg
309
+ when String
310
+ msg
311
+ when Symbol, Proc
312
+ evaluate msg
313
+ else
314
+ name
315
+ end
316
+ @requirement_messages[name] = result
321
317
  end
322
-
318
+
323
319
  def find_event_target( evt, tgt )
324
320
  case tgt
325
321
  when StateFu::State
326
322
  tgt
327
323
  when Symbol
328
- binding && binding.machine.states[ tgt ] # || raise( tgt.inspect )
324
+ binding && binding.machine.states[ tgt ]
329
325
  when NilClass
330
326
  evt.respond_to?(:target) && evt.target
331
327
  else
@@ -1,5 +1,5 @@
1
1
  module StateFu
2
- class TransitionQuery #< Array
2
+ class TransitionQuery
3
3
  attr_accessor :binding, :options, :result, :args, :block
4
4
 
5
5
  def initialize(binding, options={})
@@ -23,20 +23,46 @@ module StateFu
23
23
  end
24
24
 
25
25
  #
26
- #
26
+ #
27
27
  #
28
28
 
29
- def find( event_or_array )
30
- event, target = parse_destination(event_or_array)
29
+ # same as find, except that if there is more than one target for the event
30
+ # and only one is valid, it will return that one.
31
+ # def search(destination=nil, &block)
32
+ # # use the prepared event & target if none are supplied
33
+ # event, target = destination.nil? ? [options[:event], options[:target]] : parse_destination(destination)
34
+ # query = for_event(event).to(target)
35
+ # query.find || query.valid.singular || NilTransition.new
36
+ # end
37
+
38
+ # find a transition by event and optionally (optional if it can be inferred) target.
39
+ def find(destination=nil, &block)
40
+ # use the prepared event & target if none are supplied
41
+ event, target = destination.nil? ? [options[:event], options[:target]] : parse_destination(destination)
31
42
  _args, _block = @args, @block
32
- returning binding.new_transition(event, target) do |t|
33
- t.apply!(&_block) if _block
43
+ returning binding.new_transition(event, target) do |transition|
44
+ # return NilTransition.new if transition.nil?
45
+ transition.apply!(&_block) if _block
34
46
  if _args
35
- t.args = _args
47
+ transition.args = _args
36
48
  end
37
49
  end
38
50
  end
39
51
 
52
+ # def legal?(destination=nil, &block)
53
+ # # use the prepared event & target if none are supplied
54
+ # event, target = destination.nil? ? [options[:event], options[:target]] : parse_destination(destination)
55
+ # begin
56
+ # !!search(destination, &block)
57
+ # rescue IllegalTransition
58
+ # false
59
+ # end
60
+ # end
61
+
62
+ #
63
+ #
64
+ #
65
+
40
66
  def cyclic
41
67
  @options.merge! :cyclic => true
42
68
  self
@@ -63,7 +89,7 @@ module StateFu
63
89
  self
64
90
  end
65
91
 
66
- def for event
92
+ def for_event event
67
93
  @options.merge! :event => event
68
94
  self
69
95
  end
@@ -77,9 +103,14 @@ module StateFu
77
103
  #
78
104
  #
79
105
 
80
- def singular
106
+ def only_one
81
107
  result.first if result.length == 1
82
108
  end
109
+ alias_method :singular, :only_one
110
+
111
+ def only_one?
112
+ !!singular
113
+ end
83
114
 
84
115
  def next
85
116
  @options[:cyclic] ||= false
@@ -118,7 +149,7 @@ module StateFu
118
149
 
119
150
  def with(*args, &block)
120
151
  @args = args
121
- @block = block
152
+ @block = block if block_given?
122
153
  self
123
154
  end
124
155
 
@@ -196,17 +227,19 @@ module StateFu
196
227
  # takes a single, simple (one target only) event,
197
228
  # or an array of [event, target],
198
229
  # or one of the above with symbols in place of the objects themselves.
199
- def parse_destination(event_or_array)
200
- case event_or_array
201
- when Event, Symbol
202
- event = event_or_array
203
- target = nil
204
- when Array
205
- event, target = *event_or_array
230
+ def parse_destination(destination)
231
+ event, target = destination
232
+
233
+ unless event.is_a?(Event)
234
+ event = binding.machine.events[event]
235
+ end
236
+
237
+ unless target.is_a?(State)
238
+ target = binding.machine.states[target] rescue nil
206
239
  end
240
+
207
241
  raise ArgumentError.new( [event,target].inspect ) unless
208
- [Event, Symbol].include?(event.class) &&
209
- [State, Symbol, NilClass].include?(target.class)
242
+ [[Event, State],[Event, NilClass]].include?( [event,target].map(&:class) )
210
243
  [event, target]
211
244
  end # parse_destination
212
245
 
@@ -142,7 +142,7 @@ describe "an ActiveRecord model with StateFu included:" do
142
142
  ex = ExampleRecord.create!( :name => "exemplar" )
143
143
  ex.state_fu.state.name.should == :initial
144
144
  ex.state_fu_field.should == 'initial'
145
- t = ex.state_fu.fire!( :change )
145
+ t = ex.state_fu.change!
146
146
  t.should be_accepted
147
147
  ex.state_fu.state.name.should == :final
148
148
  ex.state_fu_field.should == 'final'
@@ -28,7 +28,7 @@ describe String do
28
28
  klone = clone
29
29
  begin
30
30
  klone.shell.escape!
31
- rescue StateFu::InvalidTransition
31
+ rescue StateFu::IllegalTransition
32
32
  end
33
33
  klone
34
34
  end
@@ -55,11 +55,11 @@ describe String do
55
55
  @str.should be_clean
56
56
  end
57
57
 
58
- it "should raise an InvalidTransition if shell.escape! is called more than once" do
58
+ it "should raise an IllegalTransition if shell.escape! is called more than once" do
59
59
  @str.shell.escape!
60
60
  @str.shell.state_name.should == :clean
61
61
 
62
- lambda { @str.shell.escape! }.should raise_error( StateFu::InvalidTransition )
62
+ lambda { @str.shell.escape! }.should raise_error( StateFu::IllegalTransition )
63
63
  end
64
64
 
65
65
  it "should modify the string when shell.escape is called" do
@@ -90,7 +90,7 @@ describe "Transition requirement reflection" do
90
90
  end # unmet requirements
91
91
 
92
92
  describe "given transition.unmet_requirement_messages" do
93
- it "should return a list of nils" do
93
+ it "should return a list of symbols" do
94
94
  @obj.state_fu.catch_plane(:america).unmet_requirement_messages.should ==
95
95
  [:papers_in_order?, :money_for_bribe?, :no_turban?, :us_visa?, :no_arrest_warrant?]
96
96
  end
@@ -88,15 +88,6 @@ describe StateFu::Transition do
88
88
  @t.should_not be_halted
89
89
  end
90
90
 
91
- it "should not be testing" do
92
- @t.should_not be_test
93
- @t.should_not be_testing
94
- end
95
-
96
- it "should be live" do
97
- @t.should be_live
98
- end
99
-
100
91
  it "should not be accepted" do
101
92
  @t.should_not be_accepted
102
93
  end
@@ -143,15 +134,6 @@ describe StateFu::Transition do
143
134
  @t.should_not be_halted
144
135
  end
145
136
 
146
- it "should not be testing" do
147
- @t.should_not be_test
148
- @t.should_not be_testing
149
- end
150
-
151
- it "should be live" do
152
- @t.should be_live
153
- end
154
-
155
137
  it "should be accepted" do
156
138
  @t.should be_accepted
157
139
  end
@@ -204,14 +186,8 @@ describe StateFu::Transition do
204
186
  trans.args.should == []
205
187
  end
206
188
 
207
- it "should be a live? transition, not a test?" do
208
- trans = @obj.state_fu.transition( :transfer )
209
- trans.should be_live
210
- trans.should_not be_test
211
- end
212
-
213
189
  it "should define any methods declared in a block given to .transition" do
214
- trans = @obj.state_fu.transition( :transfer ) do
190
+ trans = @obj.state_fu.transition( :transfer ) do
215
191
  def snoo
216
192
  return [self]
217
193
  end
@@ -232,25 +208,14 @@ describe StateFu::Transition do
232
208
 
233
209
  describe "state_fu.fire!( :transfer )" do
234
210
  it "should change the state when called" do
235
- @obj.state_fu.should respond_to( :fire! )
211
+ @obj.state_fu.should respond_to( :fire_transition! )
236
212
  @obj.state_fu.state.should == @origin
237
- @obj.state_fu.fire!( :transfer )
213
+ @obj.state_fu.fire_transition!( :transfer )
238
214
  @obj.state_fu.state.should == @target
239
215
  end
240
216
 
241
- it "should define any methods declared in the .fire! block" do
242
- trans = @obj.state_fu.fire!( :transfer ) do
243
- def snoo
244
- return [self]
245
- end
246
- end
247
- trans.should be_kind_of( StateFu::Transition )
248
- trans.should respond_to(:snoo)
249
- trans.snoo.should == [trans]
250
- end
251
-
252
217
  it "should return a transition object" do
253
- @obj.state_fu.fire!( :transfer ).should be_kind_of( StateFu::Transition )
218
+ @obj.state_fu.fire_transition!( :transfer ).should be_kind_of( StateFu::Transition )
254
219
  end
255
220
 
256
221
  end # state_fu.fire!
@@ -310,14 +275,6 @@ describe StateFu::Transition do
310
275
  end
311
276
  end
312
277
 
313
- describe "calling fire!( :transfer, :a, :b, :c => :d )" do
314
- it "should set args and options on the transition" do
315
- t = @obj.state_fu.fire!( :transfer, *@args )
316
- t.args.should == [ :a, :b, {:c =>:d} ]
317
- t.options.should == { :c => :d }
318
- end
319
- end
320
-
321
278
  describe "calling next!( :a, :b, :c => :d )" do
322
279
  it "should set args and options on the transition" do
323
280
  t = @obj.state_fu.next!( *@args )
@@ -443,14 +400,14 @@ describe StateFu::Transition do
443
400
  end
444
401
  end # state_fu.transition
445
402
 
446
- describe "state_fu.fire!" do
403
+ describe "state_fu.fire_transition!" do
447
404
  it "should raise an StateFu::UnknownTarget unless a valid targets state is supplied" do
448
405
  lambda do
449
- @obj.state_fu.fire!( :go )
406
+ @obj.state_fu.fire_transition!( :go )
450
407
  end.should raise_error( StateFu::UnknownTarget )
451
408
 
452
409
  lambda do
453
- @obj.state_fu.fire!( [ :go, :awol ] )
410
+ @obj.state_fu.fire_transition!( [ :go, :awol ] )
454
411
  end.should raise_error( StateFu::UnknownTarget )
455
412
  end
456
413
  end # state_fu.fire!
@@ -797,7 +754,7 @@ describe StateFu::Transition do
797
754
  #stub( @binding ).ok? { false }
798
755
  @obj.ok = false
799
756
  lambda do
800
- @obj.state_fu.fire!( :go )
757
+ @obj.state_fu.fire_transition!( :go )
801
758
  end.should raise_error( StateFu::RequirementError )
802
759
  end
803
760
 
@@ -1065,8 +1022,8 @@ describe StateFu::Transition do
1065
1022
  t.should be_nil
1066
1023
  end
1067
1024
 
1068
- it "should raise an InvalidTransition if next! is called" do
1069
- lambda { @binding.next! }.should raise_error( StateFu::InvalidTransition )
1025
+ it "should raise an IllegalTransition if next! is called" do
1026
+ lambda { @binding.next! }.should raise_error( StateFu::IllegalTransition )
1070
1027
  end
1071
1028
  end
1072
1029
 
@@ -22,7 +22,7 @@ describe "A door which opens and shuts:" do
22
22
  end
23
23
 
24
24
  def method_missing(method_name, *args, &block)
25
- raise NoMethodError.new("I'm just a door!")
25
+ raise NoMethodError.new("I'm just a door!" )
26
26
  end
27
27
 
28
28
  machine do
@@ -181,6 +181,7 @@ describe "A door which opens and shuts:" do
181
181
 
182
182
  it "#can_shut? when the current state is open" do
183
183
  @door.current_state.should == :open
184
+ # @door.state_fu.valid_transitions.map(&:destination).inspect
184
185
  @door.can_shut?.should == true
185
186
  @door.can_open?.should == nil # not a valid transition from this state -> nil
186
187
  end
@@ -194,14 +195,14 @@ describe "A door which opens and shuts:" do
194
195
  @door.current_state.should == :closed
195
196
  end
196
197
 
197
- it "raises a StateFu::InvalidTransition if #shut! is called when already :closed" do
198
+ it "raises a StateFu::IllegalTransition if #shut! is called when already :closed" do
198
199
  @door.current_state.should == :open
199
200
  @door.shut!.should be_true
200
201
  @door.current_state.should == :closed
201
202
  lambda do
202
203
  t = @door.shut!
203
204
  t.origin.should == :open
204
- end.should raise_error(StateFu::InvalidTransition)
205
+ end.should raise_error(StateFu::IllegalTransition)
205
206
  end
206
207
 
207
208
  it "raises StateFu::RequirementError if #open! is called when it is locked" do
@@ -250,9 +251,15 @@ describe "A door which opens and shuts:" do
250
251
  transition.target.should == :closed
251
252
  end
252
253
 
253
- it "returns a Transition on #slam" do
254
- transition = @door.slam
255
- should_be_an_unfired_transition_with_the_event_slam_from_open_to_closed( transition )
254
+ it "returns a Transition on #slam" do
255
+ @door.slam do |transition|
256
+ transition.should be_kind_of(StateFu::Transition)
257
+ transition.fired?.should == false
258
+ transition.current_state.should == :open
259
+ transition.event.should == :slam
260
+ transition.origin.should == :open
261
+ transition.target.should == :closed
262
+ end
256
263
  end
257
264
 
258
265
  it "returns a Transition on #state_fu.slam" do
@@ -396,10 +403,10 @@ describe "a simple machine, a heart which beats:" do
396
403
  @heart.heartbeats.should == [:thumpthump]
397
404
  end
398
405
 
399
- it "raise an InvalidTransition if it tries to beat after it's stopped" do
406
+ it "raise an IllegalTransition if it tries to beat after it's stopped" do
400
407
  @heart.stop!
401
408
  @heart.current_state.should == :stopped
402
- lambda { @heart.beat! }.should raise_error(StateFu::InvalidTransition)
409
+ lambda { @heart.beat! }.should raise_error(StateFu::IllegalTransition)
403
410
  end
404
411
 
405
412
  it "transition to :stopped on #next!" do
@@ -838,7 +845,7 @@ describe "sitting at a poker machine" do
838
845
  @pokie.pull_lever!
839
846
  @pokie.spinning?.should be_true
840
847
  @pokie.can_pull_lever?.should == nil
841
- lambda{ @pokie.pull_lever! }.should raise_error(StateFu::InvalidTransition)
848
+ lambda{ @pokie.pull_lever! }.should raise_error(StateFu::IllegalTransition)
842
849
  end
843
850
 
844
851
  it "makes a spinning sound while you wait" do
@@ -138,7 +138,7 @@ describe StateFu::Binding do
138
138
  describe "Instance methods" do
139
139
  before do
140
140
  end
141
- describe "fireable?" do
141
+ describe "can_transition?" do
142
142
  before do
143
143
  reset!
144
144
  make_pristine_class("Klass")
@@ -147,7 +147,7 @@ describe StateFu::Binding do
147
147
  end
148
148
  @machine = Klass.state_fu_machine do
149
149
  state :snoo do
150
- event :am_fireable, :to => :wizz do
150
+ event :fire, :to => :wizz do
151
151
  requires :tissue?
152
152
  end
153
153
  end
@@ -160,16 +160,15 @@ describe StateFu::Binding do
160
160
 
161
161
  describe "when called with arguments which would return a valid transition from .transition()" do
162
162
  it "should return true" do
163
- @obj.state_fu.fireable?(:am_fireable).should == true
163
+ @obj.state_fu.can_transition?(:fire).should == true
164
164
  end
165
165
  end
166
166
 
167
- describe "when called with arguments which would raise an InvalidTransition from .transition()" do
167
+ describe "when called with arguments which would raise an IllegalTransition from .transition()" do
168
168
  it "should return nil" do
169
169
  @obj.state_fu.name.should == :snoo
170
- lambda { @obj.state_fu.transition(:not_fireable) }.should raise_error( StateFu::InvalidTransition )
171
- lambda { @obj.state_fu.fireable?(:not_fireable) }.should_not raise_error( StateFu::InvalidTransition )
172
- @obj.state_fu.fireable?(:not_fireable).should == nil
170
+ lambda { @obj.state_fu.can_transition?(:not_fire) }.should_not raise_error( StateFu::IllegalTransition )
171
+ @obj.state_fu.can_transition?(:not_fire).should == nil
173
172
  end
174
173
  end
175
174
 
@@ -178,10 +177,12 @@ describe StateFu::Binding do
178
177
  # This would make very little sense to someone trying to understand how to use the library.
179
178
  it "should pass the arguments to any requirements to determine transition availability" do
180
179
  pending
181
- mock(@obj).tissue?() do
182
- current_transition.should be_kind_of(StateFu::Transition)
180
+ t = nil
181
+ mock(@obj).tissue?(anything) do
182
+ # current_transition.should be_kind_of(StateFu::Transition)
183
+ t << current_transition
183
184
  end #{|tr| tr.args.should == [:a,:b] }
184
- @obj.state_fu.am_fireable?(:a, :b)
185
+ @obj.state_fu.can_fire?(:a, :b)
185
186
  end
186
187
  end
187
188
 
@@ -46,7 +46,7 @@ describe StateFu::TransitionHalted do
46
46
  end
47
47
  end
48
48
 
49
- describe StateFu::InvalidTransition do
49
+ describe StateFu::IllegalTransition do
50
50
  before do
51
51
  @binding = Object.new
52
52
  @origin = Object.new
@@ -55,24 +55,24 @@ describe StateFu::InvalidTransition do
55
55
  end
56
56
 
57
57
  describe "constructor" do
58
- it "should create an InvalidTransition given a binding, event, origin & target" do
58
+ it "should create an IllegalTransition given a binding, event, origin & target" do
59
59
  pending
60
- e = StateFu::InvalidTransition.new( @binding, @event, @origin, @target )
61
- e.should be_kind_of( StateFu::InvalidTransition )
62
- e.message.should == StateFu::InvalidTransition::DEFAULT_MESSAGE
60
+ e = StateFu::IllegalTransition.new( @binding, @event, @origin, @target )
61
+ e.should be_kind_of( StateFu::IllegalTransition )
62
+ e.message.should == StateFu::IllegalTransition::DEFAULT_MESSAGE
63
63
  end
64
64
 
65
65
  it "should allow a custom message" do
66
66
  pending
67
67
  msg = 'helo'
68
- e = StateFu::InvalidTransition.new( @binding, @event, @origin, @target, msg )
69
- e.should be_kind_of( StateFu::InvalidTransition )
68
+ e = StateFu::IllegalTransition.new( @binding, @event, @origin, @target, msg )
69
+ e.should be_kind_of( StateFu::IllegalTransition )
70
70
  e.message.should == msg
71
71
  end
72
72
 
73
73
  it "should allow access to the binding, event, origin, and target" do
74
74
  pending
75
- e = StateFu::InvalidTransition.new( @binding, @event, @origin, @target )
75
+ e = StateFu::IllegalTransition.new( @binding, @event, @origin, @target )
76
76
  e.binding.should == @binding
77
77
  e.event.should == @event
78
78
  e.origin.should == @origin
@@ -61,8 +61,8 @@ describe StateFu::MethodFactory do
61
61
  end
62
62
 
63
63
  it "should call binding.fire!( :simple_event ... ) with any specified args" do
64
- mock.instance_of( StateFu::Binding ).fire!( anything, :a, :b, {:c => "d"} )
65
- t = @obj.simple_event!( nil, :a, :b, :c => "d" )
64
+ mock.instance_of( StateFu::Binding ).fire_transition!( is_a(StateFu::Event), is_a(StateFu::State), :aa, :bb, {:cc => "dd"} )
65
+ t = @obj.simple_event!( :aa, :bb, :cc => "dd" )
66
66
  end
67
67
 
68
68
  it "should fire the transition" do
@@ -107,7 +107,7 @@ describe StateFu::MethodFactory do
107
107
  end
108
108
 
109
109
  it "should add any arguments / options it is called with to the transition" do
110
- t = @binding.simple_event nil, :a, :b, :c, {'d' => 'e'}
110
+ t = @binding.simple_event :a, :b, :c, {'d' => 'e'}
111
111
  #t.should be_kind_of( StateFu::Transition )
112
112
  #t.target.should == @machine.states[:targ]
113
113
  #t.event.should == @machine.events[:simple_event]
@@ -116,21 +116,21 @@ describe StateFu::MethodFactory do
116
116
  end
117
117
  end # transition builder
118
118
 
119
- describe "method which tests if the event is fireable?" do
119
+ describe "method which tests if the event is can_transition?" do
120
120
  it "should have the name of the event suffixed with ?" do
121
121
  @binding.should respond_to(:can_simple_event?)
122
122
  end
123
123
 
124
- it "should be true when the binding says it\'s fireable?" do
125
- @binding.fireable?( :simple_event ).should == true
124
+ it "should be true when the binding says it\'s can_transition?" do
125
+ @binding.can_transition?( :simple_event ).should == true
126
126
  @binding.can_simple_event?.should == true
127
127
  end
128
128
 
129
- it "should be false when the binding says it\'s not fireable?" do
130
- mock( @binding ).fireable?( anything ) { false }
129
+ it "should be false when the binding says it\'s not can_transition?" do
130
+ mock( @binding ).can_transition?( is_a(StateFu::Event), is_a(StateFu::State) ) { false }
131
131
  @binding.can_simple_event?.should == false
132
132
  end
133
- end # fireable?
133
+ end # can_transition?
134
134
 
135
135
  describe "bang (!) method which creates, fires and returns a transition" do
136
136
  it "should have the name of the event suffixed with a bang (!)" do
@@ -144,7 +144,7 @@ describe StateFu::MethodFactory do
144
144
  end
145
145
 
146
146
  it "should pass any arguments to the transition as args / options" do
147
- t = @binding.simple_event!( nil, :a, :b, {'c' => :d } )
147
+ t = @binding.simple_event!( :a, :b, {'c' => :d } )
148
148
  t.should be_kind_of( StateFu::Transition )
149
149
  t.args.should == [:a, :b, {'c' => :d} ]
150
150
  t.options.should == { :c => :d }
@@ -178,15 +178,15 @@ describe StateFu::MethodFactory do
178
178
  end
179
179
 
180
180
  it "should raise an error if called without any arguments" do
181
- lambda { @binding.complex_event() }.should raise_error( StateFu::UnknownTarget )
181
+ lambda { @binding.complex_event() }.should raise_error( ArgumentError )
182
182
  end
183
183
 
184
184
  it "should raise an ArgumentError if called with a nonexistent target state" do
185
185
  lambda { @binding.complex_event(:nonexistent) }.should raise_error( StateFu::UnknownTarget )
186
186
  end
187
187
 
188
- it "should raise an InvalidTransition if called with an invalid target state" do
189
- lambda { @binding.complex_event(:orphan) }.should raise_error( StateFu::InvalidTransition )
188
+ it "should raise an IllegalTransition if called with an invalid target state" do
189
+ lambda { @binding.complex_event(:orphan) }.should raise_error( StateFu::IllegalTransition )
190
190
  end
191
191
 
192
192
  it "should return a transition to the specified state if supplied a valid state" do
@@ -204,7 +204,7 @@ describe StateFu::MethodFactory do
204
204
  end
205
205
  end # transition builder
206
206
 
207
- describe "method which tests if the event is fireable?" do
207
+ describe "method which tests if the event is can_transition?" do
208
208
  it "should have the name of the event suffixed with ?" do
209
209
  @binding.should respond_to(:can_complex_event?)
210
210
  end
@@ -212,20 +212,15 @@ describe StateFu::MethodFactory do
212
212
  it "should require a valid state name" do
213
213
  lambda { @binding.can_complex_event?(:nonexistent) }.should raise_error( StateFu::UnknownTarget )
214
214
  lambda { @binding.can_complex_event?(:orphan) }.should_not raise_error()
215
- @binding.can_complex_event?(:orphan).should == nil
215
+ @binding.can_complex_event?(:orphan).should == false
216
216
  lambda { @binding.can_complex_event?(:x) }.should_not raise_error
217
217
  end
218
218
 
219
- it "should be true when the binding says the event is fireable? " do
220
- @binding.fireable?( [:complex_event, :x] ).should == true
219
+ it "should be true when the binding says the event is can_transition? " do
220
+ @binding.can_transition?( :complex_event, :x ).should == true
221
221
  @binding.can_complex_event?(:x).should == true
222
222
  end
223
-
224
- it "should be false when the binding says the event is not fireable?" do
225
- mock( @binding ).fireable?( anything ) { false }
226
- @binding.can_complex_event?(:x).should == false
227
- end
228
- end # fireable?
223
+ end # can_transition?
229
224
 
230
225
  describe "bang (!) method which creates, fires and returns a transition" do
231
226
  it "should have the name of the event suffixed with a bang (!)" do
@@ -234,7 +229,7 @@ describe StateFu::MethodFactory do
234
229
 
235
230
  it "should require a valid state name" do
236
231
  lambda { @binding.complex_event!(:nonexistent) }.should raise_error( StateFu::UnknownTarget )
237
- lambda { @binding.complex_event!(:orphan) }.should raise_error( StateFu::InvalidTransition )
232
+ lambda { @binding.complex_event!(:orphan) }.should raise_error( StateFu::IllegalTransition )
238
233
  lambda { @binding.complex_event!(:x) }.should_not raise_error
239
234
  end
240
235
 
@@ -350,7 +345,7 @@ describe StateFu::MethodFactory do
350
345
  end
351
346
 
352
347
  describe "next_state!" do
353
- it "should raise_error( InvalidTransition )" do
348
+ it "should raise_error( IllegalTransition )" do
354
349
  lambda { @binding.next_state! }.should raise_error( StateFu::TransitionNotFound )
355
350
  end
356
351
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: davidlee-state-fu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Lee
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-25 00:00:00 -07:00
12
+ date: 2009-08-26 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -58,6 +58,7 @@ files:
58
58
  - lib/state_fu/machine.rb
59
59
  - lib/state_fu/method_factory.rb
60
60
  - lib/state_fu/methodical.rb
61
+ - lib/state_fu/nil_transition.rb
61
62
  - lib/state_fu/persistence.rb
62
63
  - lib/state_fu/persistence/active_record.rb
63
64
  - lib/state_fu/persistence/attribute.rb
@@ -110,7 +111,6 @@ files:
110
111
  - README.textile
111
112
  has_rdoc: false
112
113
  homepage: http://github.com/davidlee/state-fu
113
- licenses:
114
114
  post_install_message:
115
115
  rdoc_options:
116
116
  - --charset=UTF-8
@@ -131,7 +131,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
131
  requirements: []
132
132
 
133
133
  rubyforge_project: state-fu
134
- rubygems_version: 1.3.5
134
+ rubygems_version: 1.2.0
135
135
  signing_key:
136
136
  specification_version: 3
137
137
  summary: A rich library for state-oriented programming with state machines / workflows