finite_machine 0.10.2 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/Gemfile +1 -1
  4. data/README.md +73 -35
  5. data/assets/finite_machine_logo.png +0 -0
  6. data/lib/finite_machine.rb +0 -7
  7. data/lib/finite_machine/async_proxy.rb +1 -2
  8. data/lib/finite_machine/dsl.rb +13 -14
  9. data/lib/finite_machine/event_definition.rb +32 -35
  10. data/lib/finite_machine/events_chain.rb +183 -37
  11. data/lib/finite_machine/hook_event.rb +47 -42
  12. data/lib/finite_machine/logger.rb +3 -4
  13. data/lib/finite_machine/observer.rb +27 -11
  14. data/lib/finite_machine/state_definition.rb +66 -0
  15. data/lib/finite_machine/state_machine.rb +177 -99
  16. data/lib/finite_machine/subscribers.rb +17 -6
  17. data/lib/finite_machine/thread_context.rb +1 -1
  18. data/lib/finite_machine/transition.rb +45 -173
  19. data/lib/finite_machine/transition_builder.rb +24 -6
  20. data/lib/finite_machine/transition_event.rb +5 -4
  21. data/lib/finite_machine/undefined_transition.rb +32 -0
  22. data/lib/finite_machine/version.rb +1 -1
  23. data/spec/spec_helper.rb +1 -0
  24. data/spec/unit/async_events_spec.rb +24 -18
  25. data/spec/unit/callbacks_spec.rb +0 -19
  26. data/spec/unit/event_names_spec.rb +19 -0
  27. data/spec/unit/events_chain/add_spec.rb +25 -0
  28. data/spec/unit/events_chain/cancel_transitions_spec.rb +22 -0
  29. data/spec/unit/events_chain/choice_transition_spec.rb +28 -0
  30. data/spec/unit/events_chain/clear_spec.rb +7 -18
  31. data/spec/unit/events_chain/events_spec.rb +18 -0
  32. data/spec/unit/events_chain/inspect_spec.rb +14 -17
  33. data/spec/unit/events_chain/match_transition_spec.rb +37 -0
  34. data/spec/unit/events_chain/move_to_spec.rb +48 -0
  35. data/spec/unit/events_chain/states_for_spec.rb +17 -0
  36. data/spec/unit/events_spec.rb +119 -27
  37. data/spec/unit/hook_event/build_spec.rb +15 -0
  38. data/spec/unit/hook_event/eql_spec.rb +3 -4
  39. data/spec/unit/hook_event/initialize_spec.rb +14 -11
  40. data/spec/unit/hook_event/notify_spec.rb +14 -0
  41. data/spec/unit/{initialize_spec.rb → initial_spec.rb} +1 -1
  42. data/spec/unit/inspect_spec.rb +1 -1
  43. data/spec/unit/logger_spec.rb +4 -5
  44. data/spec/unit/subscribers_spec.rb +20 -9
  45. data/spec/unit/transition/check_conditions_spec.rb +54 -0
  46. data/spec/unit/transition/inspect_spec.rb +2 -2
  47. data/spec/unit/transition/matches_spec.rb +23 -0
  48. data/spec/unit/transition/states_spec.rb +31 -0
  49. data/spec/unit/transition/to_state_spec.rb +27 -0
  50. data/spec/unit/trigger_spec.rb +22 -0
  51. data/spec/unit/undefined_transition/eql_spec.rb +17 -0
  52. data/tasks/console.rake +1 -0
  53. metadata +39 -23
  54. data/lib/finite_machine/event.rb +0 -146
  55. data/spec/unit/event/add_spec.rb +0 -16
  56. data/spec/unit/event/eql_spec.rb +0 -37
  57. data/spec/unit/event/initialize_spec.rb +0 -38
  58. data/spec/unit/event/inspect_spec.rb +0 -21
  59. data/spec/unit/event/next_transition_spec.rb +0 -35
  60. data/spec/unit/events_chain/check_choice_conditions_spec.rb +0 -20
  61. data/spec/unit/events_chain/insert_spec.rb +0 -26
  62. data/spec/unit/events_chain/select_transition_spec.rb +0 -23
  63. data/spec/unit/transition/parse_states_spec.rb +0 -42
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: edb4b2a96673bef5c94c26d477821d2e59a5f756
4
- data.tar.gz: 518346cb8ac30326a5a9550f6b0b18bea9de5918
3
+ metadata.gz: e70496d1e626025a2c8ad75e0c66f5dfacb5d1c5
4
+ data.tar.gz: 30b266427c011d60d77254c0740d34c843a55732
5
5
  SHA512:
6
- metadata.gz: d179ed858abc96e2776de1f45278b261ce50f8adccf1841420c334a4f2427d0999ee3cc46e40c263bff62cadbf68284a619d491f8ea8016cfa0d3c576d1dd40c
7
- data.tar.gz: 2036811dac682bb9decb39a5c39e5cc7c026109db57e97946dd3ca26b8106d109eaecffd200c6c8481cf5c5fb3a5fff6eaae5ed188b9e4bd1ab2d3ea1276aa6a
6
+ metadata.gz: d7e2d93b571c333c64ec880d3665abdf1ca65b8abd4ba2389b7d6451ad179e4aca67c42811829bdb6cad23a61993efdaf1c225cb6927572222b6bb76828bec88
7
+ data.tar.gz: d72998f62c65ed6c5f74021926db45e99cfaf065665627f4a8f2e485215397c712326d80a36aa20e281879bb9d79dcab5f670d0ca71736d7bc6e09c4edb7182a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ 0.11.0 (Oct 11, 2015)
2
+
3
+ * Add UndefinedTransition to mark self transition(e.i. no transition found)
4
+ * Add StateDefinition for state query methods
5
+ * Add #trigger and #trigger! to StateMachine to allow manual firing of events and split between dangerous and non-dangerous versions of api.
6
+ * Change ThreadContext to require per thread setup
7
+ * Change Transition to stop relying on global transitions
8
+ * Change EventChain to manage all internal transitions
9
+ * Change Subscribers to remove unnecessary parameter dependency
10
+ * Change StateMachine public interface to clarify available methods
11
+ * Change HookEvent to accept event name and from state
12
+ * Remove Event class as duplicate of Transition
13
+ * Remove unnecessary checks for StateMachine#can?
14
+ * Fix bug in Transition with current transition matching
15
+ * Fix bug in Observer with cancelling inside event callback
16
+
1
17
  0.10.2 (July 5, 2015)
2
18
 
3
19
  * Fix to run 'on_after' callbacks even when event cancalled by @craiglittle
data/Gemfile CHANGED
@@ -5,7 +5,7 @@ gemspec
5
5
  group :development do
6
6
  gem 'pry', '~> 0.10.1'
7
7
  gem 'rake', '~> 10.4.2'
8
- gem 'rspec', '~> 3.2.0'
8
+ gem 'rspec', '~> 3.3.0'
9
9
  gem 'yard', '~> 0.8.7'
10
10
  end
11
11
 
data/README.md CHANGED
@@ -1,3 +1,6 @@
1
+ <div align="center">
2
+ <a href="http://peter-murach.github.io/finite_machine/"><img width="236" src="https://raw.githubusercontent.com/peter-murach/finite_machine/master/assets/finite_machine_logo.png" alt="finite machine logo" /></a>
3
+ </div>
1
4
  # FiniteMachine
2
5
  [![Gem Version](https://badge.fury.io/rb/finite_machine.svg)][gem]
3
6
  [![Build Status](https://secure.travis-ci.org/peter-murach/finite_machine.svg?branch=master)][travis]
@@ -45,18 +48,19 @@ Or install it yourself as:
45
48
  ## Contents
46
49
 
47
50
  * [1. Usage](#1-usage)
48
- * [1.1 Current](#11-current)
49
- * [1.2 Initial](#12-initial)
50
- * [1.3 Terminal](#13-terminal)
51
+ * [1.1 current](#11-current)
52
+ * [1.2 initial](#12-initial)
53
+ * [1.3 terminal](#13-terminal)
51
54
  * [1.4 is?](#14-is)
52
55
  * [1.5 can? and cannot?](#15-can-and-cannot)
53
- * [1.6 states](#16-states)
54
- * [1.7 target](#17-target)
55
- * [1.8 Alias target](#18-alias-target)
56
- * [1.9 restore!](#19-restore)
56
+ * [1.6 target](#16-target)
57
+ * [1.7 Alias target](#17-alias-target)
58
+ * [1.8 restore!](#18-restore)
59
+ * [1.9 states](#19-states)
60
+ * [1.10 event names](#110-event-names)
57
61
  * [2. Transitions](#2-transitions)
58
62
  * [2.1 Performing transitions](#21-performing-transitions)
59
- * [2.2 Forcing transitions](#22-forcing-transitions)
63
+ * [2.2 Dangerous transitions](#22-dangerous-transitions)
60
64
  * [2.3 Asynchronous transitions](#23-asynchronous-transitions)
61
65
  * [2.4 Multiple from states](#24-multiple-from-states)
62
66
  * [2.5 From :any state](#25-from-any-state)
@@ -158,7 +162,7 @@ fm = FiniteMachine.define do
158
162
  end
159
163
 
160
164
  fm.current # => :none
161
- fm.start
165
+ fm.start # => true
162
166
  fm.current # => :green
163
167
  ```
164
168
 
@@ -253,9 +257,9 @@ When the terminal state has been specified, you can use `terminated?` method on
253
257
 
254
258
  ```ruby
255
259
  fm.terminated? # => false
256
- fm.slow
260
+ fm.slow # => true
257
261
  fm.terminated? # => false
258
- fm.stop
262
+ fm.stop # => true
259
263
  fm.terminated? # => true
260
264
  ```
261
265
 
@@ -300,20 +304,12 @@ end
300
304
  fm.can?(:slow) # => true
301
305
  fm.can?(:stop) # => false
302
306
 
303
- fm.slow
307
+ fm.slow # => true
304
308
  fm.can?(:stop, :breaks) # => true
305
309
  fm.can?(:stop, :no_breaks) # => false
306
310
  ```
307
311
 
308
- ### 1.6 states
309
-
310
- You can use the `states` method to return an array of all the states for a given state machine.
311
-
312
- ```ruby
313
- fm.states # => [:none, :green, :yellow, :red]
314
- ```
315
-
316
- ### 1.7 target
312
+ ### 1.6 target
317
313
 
318
314
  If you need to execute some external code in the context of the current state machine use `target` helper.
319
315
 
@@ -376,7 +372,7 @@ fm = FiniteMachine.define do
376
372
  end
377
373
  ```
378
374
 
379
- ### 1.8 Alias target
375
+ ### 1.7 Alias target
380
376
 
381
377
  If you need to better express the intention behind the target name, in particular when calling actions in callbacks, you can use the `alias_target` helper:
382
378
 
@@ -401,7 +397,7 @@ fm = FiniteMachine.define do
401
397
  end
402
398
  ```
403
399
 
404
- ### 1.9 restore!
400
+ ### 1.8 restore!
405
401
 
406
402
  In order to set the machine to a given state and thus skip triggering callbacks use the `restore!` method:
407
403
 
@@ -411,6 +407,22 @@ fm.restore!(:neutral)
411
407
 
412
408
  This method may be suitable when used testing your state machine or in restoring the state from datastore.
413
409
 
410
+ ### 1.9 states
411
+
412
+ You can use the `states` method to return an array of all the states for a given state machine.
413
+
414
+ ```ruby
415
+ fm.states # => [:none, :green, :yellow, :red]
416
+ ```
417
+
418
+ ### 1.10 event names
419
+
420
+ To find out all the event names supported by the state machine issue `event_names` method:
421
+
422
+ ```ruby
423
+ fm.event_names # => [:init, :ready, :go, :stop]
424
+ ```
425
+
414
426
  ## 2 Transitions
415
427
 
416
428
  The `events` scope exposes the `event` helper to define possible state transitions.
@@ -434,23 +446,41 @@ The following methods trigger transitions for the example state machine.
434
446
 
435
447
  ### 2.1 Performing transitions
436
448
 
437
- In order to transition to the next reachable state, simply call the event's name on the **FiniteMachine** instance.
449
+ In order to transition to the next reachable state, simply call the event's name on the **FiniteMachine** instance. If the transition succeeds the `true` value is returned, otherwise `false`.
438
450
 
439
451
  ```ruby
440
- fm.ready
452
+ fm.ready # => true
441
453
  fm.current # => :yellow
442
454
  ```
443
455
 
444
- Furthermore, you can pass additional parameters with the method call that will be available in the triggered callback.
456
+ If you prefer you can also use `trigger` method to fire any event by its name:
445
457
 
446
458
  ```ruby
447
- fm.go('Piotr!')
459
+ fm.trigger(:ready) # => true
460
+ ```
461
+
462
+ Furthermore, you can pass additional parameters with the method call that will be available in the triggered callback as well as used by any present guarding conditions.
463
+
464
+ ```ruby
465
+ fm.go('Piotr!') # => true
448
466
  fm.current # => :green
449
467
  ```
450
468
 
451
- ### 2.2 Forcing transitions
469
+ By default **FiniteMachine** will swallow all exceptions when and return `false` on failure. If you prefer to be notified when illegal transition occurs see [Dangerous transitions](#22-dangerous-transitions).
470
+
471
+ ### 2.2 Dangerous transitions
472
+
473
+ When you declare event, for instance `ready`, the **FiniteMachine** will provide a dangerous version with a bang `ready!`. In the case when you attempt to perform illegal transition or **FiniteMachine** throws internall error, the state machine will propagate the errors. You can use handlers to decide how to handle errors on case by case basis see [6. Errors](#6-errors)
474
+
475
+ ```ruby
476
+ fm.ready! # => raises FiniteMachine::InvalidStateError
477
+ ```
478
+
479
+ If you prefer you can also use `trigger!` method to fire event:
452
480
 
453
- When you declare event, for instance `ready`, the **FiniteMachine** will provide a dangerous version with a bang `ready!`. In the case when you need to perform transition disregarding current state reachable states, the `ready!` will transition without any validations or callbacks.
481
+ ```ruby
482
+ fm.trigger!(:ready)
483
+ ```
454
484
 
455
485
  ### 2.3 Asynchronous transitions
456
486
 
@@ -607,7 +637,7 @@ fm.go(:yellow) # doesn't transition
607
637
  fm.go # raises ArgumentError
608
638
  ```
609
639
 
610
- **Note** If you specify condition with a given arguments then you need to call an event with the exact number of arguments, otherwise you will get `ArgumentError`. Thus in above scenario to prevent errors specify condition like so:
640
+ **Note** If you specify condition with a given number of arguments then you need to call an event with the exact number of arguments, otherwise you will get `ArgumentError`. Thus in above scenario to prevent errors specify condition like so:
611
641
 
612
642
  ```ruby
613
643
  if: -> (context, *args) { ... }
@@ -805,7 +835,7 @@ end
805
835
 
806
836
  ## 5 Callbacks
807
837
 
808
- You can watch state machine events and the information they provide by registering a callback. The following 5 types of callbacks are available in **FiniteMachine**:
838
+ You can watch state machine events and the information they provide by registering one or more predefined callback types. The following 5 types of callbacks are available in **FiniteMachine**:
809
839
 
810
840
  * `on_enter`
811
841
  * `on_transition`
@@ -813,9 +843,15 @@ You can watch state machine events and the information they provide by registeri
813
843
  * `on_before`
814
844
  * `on_after`
815
845
 
816
- Use the `callbacks` scope to introduce the listeners. You can register a callback to listen for state changes or events being triggered. Use the state or event name as a first parameter to the callback followed by a list arguments that you expect to receive.
846
+ Use the `callbacks` scope to introduce the listeners. You can register a callback to listen for state changes or events being triggered.
847
+
848
+ Use the state or event name as a first parameter to the callback helper followed by block with event argument and a list arguments that you expect to receive like so:
849
+
850
+ ```ruby
851
+ on_enter :green { |event, a, b, c| ... }
852
+ ```
817
853
 
818
- When you subscribe to the `:green` state change, the callback will be called whenever someone instruments change for that state. The same will happen on subscription to event `ready`, namely, the callback will be called each time the state transition method is called.
854
+ When you subscribe to the `:green` state change, the callback will be called whenever someone triggers event that transitions in or out of that state. The same will happen on subscription to event `ready`, namely, the callback will be called each time the state transition method is triggered regardless of the states it transitions from or to.
819
855
 
820
856
  ```ruby
821
857
  fm = FiniteMachine.define do
@@ -838,6 +874,8 @@ fm.ready(1, 2, 3)
838
874
  fm.go('Piotr!')
839
875
  ```
840
876
 
877
+ **Note** Regardless of how the state is entered or exited, all the associated callbacks will be executed. This provides means for guaranteed initialization and cleanup.
878
+
841
879
  ### 5.1 on_enter
842
880
 
843
881
  The `on_enter` callback is executed before given state change is fired. By passing state name you can narrow down the listener to only watch out for enter state changes. Otherwise, all enter state changes will be watched.
@@ -878,8 +916,8 @@ event :go, :red => :yellow
878
916
 
879
917
  then by calling `go` event the following callbacks in the following sequence will be executed:
880
918
 
881
- * `on_before :go` - callback before the `go` event
882
919
  * `on_before` - generic callback before `any` event
920
+ * `on_before :go` - callback before the `go` event
883
921
  * `on_exit :red` - callback for the `:red` state exit
884
922
  * `on_exit` - generic callback for exit from `any` state
885
923
  * `on_transition :yellow` - callback for the `:red` to `:yellow` transition
@@ -1325,7 +1363,7 @@ car.reverse_lights_on? # => true
1325
1363
 
1326
1364
  In order to integrate **FiniteMachine** with ActiveRecord simply add a method with state machine definition. You can also define the state machine in separate module to aid reusability. Once the state machine is defined use the `target` helper to reference the current class. Having defined `target` you call ActiveRecord methods inside the callbacks to persist the state.
1327
1365
 
1328
- You can use the `restore!` method to specify which state the **FininteMachine** should be put back into as follows:
1366
+ You can use the `restore!` method to specify which state the **FiniteMachine** should be put back into as follows:
1329
1367
 
1330
1368
  ```ruby
1331
1369
  class Account < ActiveRecord::Base
Binary file
@@ -16,11 +16,8 @@ require "finite_machine/async_proxy"
16
16
  require "finite_machine/async_call"
17
17
  require "finite_machine/hook_event"
18
18
  require "finite_machine/env"
19
- require "finite_machine/event"
20
- require "finite_machine/event_definition"
21
19
  require "finite_machine/event_queue"
22
20
  require "finite_machine/events_chain"
23
- require "finite_machine/hooks"
24
21
  require "finite_machine/logger"
25
22
  require "finite_machine/transition"
26
23
  require "finite_machine/transition_builder"
@@ -29,7 +26,6 @@ require "finite_machine/dsl"
29
26
  require "finite_machine/definition"
30
27
  require "finite_machine/state_machine"
31
28
  require "finite_machine/subscribers"
32
- require "finite_machine/state_parser"
33
29
  require "finite_machine/observer"
34
30
  require "finite_machine/listener"
35
31
  require "finite_machine/two_phase_lock"
@@ -53,9 +49,6 @@ module FiniteMachine
53
49
  # Returned when transition is cancelled in callback
54
50
  CANCELLED = 2
55
51
 
56
- # Returned when transition has not changed the state
57
- NOTRANSITION = 3
58
-
59
52
  # When transition between states is invalid
60
53
  TransitionError = Class.new(::StandardError)
61
54
 
@@ -4,7 +4,6 @@ module FiniteMachine
4
4
  # An asynchronous messages proxy
5
5
  class AsyncProxy
6
6
  include Threadable
7
- include ThreadContext
8
7
 
9
8
  attr_threadsafe :context
10
9
 
@@ -25,7 +24,7 @@ module FiniteMachine
25
24
  callable = Callable.new(method_name)
26
25
  async_call = AsyncCall.new(context, callable, *args, &block)
27
26
 
28
- event_queue << async_call
27
+ context.event_queue << async_call
29
28
  end
30
29
  end # AsyncProxy
31
30
  end # FiniteMachine
@@ -89,7 +89,7 @@ module FiniteMachine
89
89
  # @api public
90
90
  def initial(value, options = {})
91
91
  state = (value && !value.is_a?(Hash)) ? value : raise_missing_state
92
- name, self.defer, silent = parse(options)
92
+ name, self.defer, silent = *parse_initial(options)
93
93
  self.initial_event = name
94
94
  event(name, FiniteMachine::DEFAULT_STATE => state, silent: silent)
95
95
  end
@@ -191,7 +191,7 @@ module FiniteMachine
191
191
  #
192
192
  # @api public
193
193
  def handlers(&block)
194
- errors.call(&block)
194
+ errors_dsl.call(&block)
195
195
  end
196
196
 
197
197
  # Decide whether to log transitions
@@ -207,27 +207,24 @@ module FiniteMachine
207
207
  #
208
208
  # @api private
209
209
  def initialize_attrs
210
- attrs[:initial] and initial(attrs[:initial])
211
- attrs[:target] and target(attrs[:target])
212
- attrs[:terminal] and terminal(attrs[:terminal])
210
+ attrs[:initial] && initial(attrs[:initial])
211
+ attrs[:target] && target(attrs[:target])
212
+ attrs[:terminal] && terminal(attrs[:terminal])
213
213
  log_transitions(attrs.fetch(:log_transitions, false))
214
214
  end
215
215
 
216
216
  # Parse initial options
217
217
  #
218
- # @param [Object] value
218
+ # @param [Hash] options
219
+ # the options to extract for initial state setup
219
220
  #
220
221
  # @return [Array[Symbol,String]]
221
222
  #
222
223
  # @api private
223
- def parse(value)
224
- if value.is_a?(Hash)
225
- [value.fetch(:event) { FiniteMachine::DEFAULT_EVENT_NAME },
226
- value.fetch(:defer) { false },
227
- value.fetch(:silent) { true }]
228
- else
229
- [FiniteMachine::DEFAULT_EVENT_NAME, false, true]
230
- end
224
+ def parse_initial(options)
225
+ [options.fetch(:event) { FiniteMachine::DEFAULT_EVENT_NAME },
226
+ options.fetch(:defer) { false },
227
+ options.fetch(:silent) { true }]
231
228
  end
232
229
 
233
230
  # Raises missing state error
@@ -246,6 +243,7 @@ module FiniteMachine
246
243
 
247
244
  # A DSL for describing events
248
245
  class EventsDSL < GenericDSL
246
+ include Safety
249
247
  # Create event and associate transition
250
248
  #
251
249
  # @example
@@ -257,6 +255,7 @@ module FiniteMachine
257
255
  # @api public
258
256
  def event(name, attrs = {}, &block)
259
257
  sync_exclusive do
258
+ detect_event_conflict!(name)
260
259
  attributes = attrs.merge!(name: name)
261
260
  if block_given?
262
261
  merger = ChoiceMerger.new(machine, attributes)
@@ -9,76 +9,73 @@ module FiniteMachine
9
9
  # @api private
10
10
  class EventDefinition
11
11
  include Threadable
12
- include Safety
13
12
 
14
13
  # The current state machine
15
14
  attr_threadsafe :machine
16
15
 
17
- # Initialize an EventBuilder
16
+ # Initialize an EventDefinition
18
17
  #
19
- # @param [FiniteMachine::StateMachine] machine
18
+ # @param [StateMachine] machine
20
19
  #
21
20
  # @api private
22
21
  def initialize(machine)
23
- @machine = machine
22
+ self.machine = machine
24
23
  end
25
24
 
26
25
  # Define transition event names as state machine events
27
26
  #
28
- # @param [Transition] transition
29
- # the transition for which event definition is created
27
+ # @param [Symbol] event_name
28
+ # the event name for which definition is created
30
29
  #
31
- # @return [Transition]
30
+ # @return [nil]
32
31
  #
33
- # @api private
34
- def apply(transition)
35
- name = transition.name
36
- detect_event_conflict!(name)
37
- if machine.singleton_class.send(:method_defined?, name)
38
- machine.events_chain.insert(name, transition)
39
- else
40
- define_event_transition(name, transition)
41
- define_event_bang(name)
42
- end
43
- transition
32
+ # @api public
33
+ def apply(event_name, silent = false)
34
+ define_event_transition(event_name, silent)
35
+ define_event_bang(event_name, silent)
44
36
  end
45
37
 
46
38
  private
47
39
 
48
40
  # Define transition event
49
41
  #
50
- # @param [Symbol] name
42
+ # @param [Symbol] event_name
51
43
  # the event name
52
44
  #
53
- # @param [FiniteMachine::Transition] transition
54
- # the transition this event is associated with
45
+ # @param [Boolean] silent
46
+ # if true don't trigger callbacks, otherwise do
55
47
  #
56
48
  # @return [nil]
57
49
  #
58
50
  # @api private
59
- def define_event_transition(name, transition)
60
- silent = transition.silent
61
- _event = Event.new(machine, name: name, silent: silent)
62
- _event << transition
63
- machine.events_chain.add(name, _event)
64
-
65
- machine.send(:define_singleton_method, name) do |*args, &block|
66
- _event.trigger(*args, &block)
51
+ def define_event_transition(event_name, silent)
52
+ machine.send(:define_singleton_method, event_name) do |*data, &block|
53
+ if silent
54
+ machine.transition(event_name, *data, &block)
55
+ else
56
+ machine.trigger(event_name, *data, &block)
57
+ end
67
58
  end
68
59
  end
69
60
 
70
- # Define event that skips validations
61
+ # Define event that skips validations and callbacks
71
62
  #
72
- # @param [Symbol] name
63
+ # @param [Symbol] event_name
73
64
  # the event name
74
65
  #
66
+ # @param [Boolean] silent
67
+ # if true don't trigger callbacks, otherwise do
68
+ #
75
69
  # @return [nil]
76
70
  #
77
71
  # @api private
78
- def define_event_bang(name)
79
- machine.send(:define_singleton_method, "#{name}!") do
80
- transitions = machine.transitions[name]
81
- machine.state = transitions.values[0]
72
+ def define_event_bang(event_name, silent)
73
+ machine.send(:define_singleton_method, "#{event_name}!") do |*data, &block|
74
+ if silent
75
+ machine.transition!(event_name, *data, &block)
76
+ else
77
+ machine.trigger!(event_name, *data, &block)
78
+ end
82
79
  end
83
80
  end
84
81
  end # EventBuilder