transitions 0.1.0 → 0.1.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 (28) hide show
  1. data/.rvmrc +1 -1
  2. data/CHANGELOG.md +8 -0
  3. data/README.rdoc +27 -21
  4. data/lib/transitions/event.rb +4 -0
  5. data/lib/transitions/machine.rb +3 -5
  6. data/lib/transitions/state.rb +2 -19
  7. data/lib/transitions/version.rb +1 -1
  8. data/test/{test_active_record.rb → active_record/test_active_record.rb} +7 -98
  9. data/test/active_record/test_active_record_scopes.rb +74 -0
  10. data/test/{test_active_record_timestamps.rb → active_record/test_active_record_timestamps.rb} +17 -9
  11. data/test/{test_event.rb → event/test_event.rb} +0 -0
  12. data/test/{test_event_arguments.rb → event/test_event_arguments.rb} +0 -0
  13. data/test/{test_event_being_fired.rb → event/test_event_being_fired.rb} +0 -0
  14. data/test/event/test_event_checks.rb +34 -0
  15. data/test/helper.rb +13 -11
  16. data/test/{test_available_states_listing.rb → machine/test_available_states_listing.rb} +1 -1
  17. data/test/{test_machine.rb → machine/test_machine.rb} +4 -0
  18. data/test/{test_state.rb → state/test_state.rb} +5 -35
  19. data/test/state/test_state_predicate_method.rb +20 -0
  20. data/test/{test_state_transition.rb → state_transition/test_state_transition.rb} +0 -0
  21. data/test/state_transition/test_state_transition_event_failed_callback.rb +36 -0
  22. data/test/state_transition/test_state_transition_event_fired_callback.rb +44 -0
  23. data/test/{test_state_transition_guard_check.rb → state_transition/test_state_transition_guard_check.rb} +0 -0
  24. data/test/{test_state_transition_callbacks.rb → state_transition/test_state_transition_on_transition_callback.rb} +0 -8
  25. data/test/{test_state_transition_success_callback.rb → state_transition/test_state_transition_success_callback.rb} +0 -11
  26. data/transitions.gemspec +2 -2
  27. metadata +26 -22
  28. data/test/db/create_db.rb +0 -22
data/.rvmrc CHANGED
@@ -1 +1 @@
1
- rvm 1.9.2-p290@transitions --create
1
+ rvm 1.9.3@transitions --create
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ # 1.0.1
2
+
3
+ * (troessner) Remove feature:
4
+ `Do not override existing methods when defining state query methods but warn the user.`
5
+ since this turned out to cause some problems when loading models, see
6
+ https://github.com/troessner/transitions/issues/62 for details.
7
+ * (bnmrrs) Add helper methods to check if a given transition is possible.
8
+
1
9
  # 1.0.0
2
10
 
3
11
  (troessner) Remove suppport for multipe state machines
data/README.rdoc CHANGED
@@ -1,14 +1,14 @@
1
- = Travis Build Status
1
+ === Travis Build Status
2
2
 
3
3
  {<img src="https://secure.travis-ci.org/troessner/transitions.png?branch=master"/>}[http://travis-ci.org/troessner/transitions]
4
4
 
5
- = Synopsis
5
+ === Synopsis
6
6
 
7
7
  <tt>transitions</tt> is a ruby state machine implementation.
8
8
 
9
- = Installation
9
+ === Installation
10
10
 
11
- == Rails
11
+ ==== Rails
12
12
 
13
13
  This goes into your Gemfile:
14
14
 
@@ -18,11 +18,11 @@ This goes into your Gemfile:
18
18
 
19
19
  include ActiveModel::Transitions
20
20
 
21
- == Standalone
21
+ ==== Standalone
22
22
 
23
23
  gem install transitions
24
24
 
25
- = Using transitions
25
+ === Using transitions
26
26
 
27
27
  class Product
28
28
  include ActiveModel::Transitions
@@ -51,15 +51,18 @@ If this is not the case for you you have to add
51
51
 
52
52
  whereever you load your dependencies in your application.
53
53
 
54
- = Features
54
+ <b>A word of warning:</b> Use symbols, not strings for declaring the state machine. Using strings is *not* supported as is using whitespace in names (because `transitions` possibly generates methods out of this).
55
55
 
56
- == Events
56
+ === Features
57
57
 
58
- When you declare an event, say <tt>discontinue</tt>, two methods are declared for
59
- you: <tt>discontinue</tt> and <tt>discontinue!</tt>. Both events will modify the <tt>state</tt> attribute on successful transition,
60
- but only the bang(!)-version will call <tt>save!</tt>.
58
+ ==== Events
61
59
 
62
- == Automatic scope generation
60
+ When you declare an event, say <tt>discontinue</tt>, three methods are declared for
61
+ you: <tt>discontinue</tt>, <tt>discontinue!</tt> and <tt>can_discontinue?</tt>. The first two events will modify the <tt>state</tt> attribute on successful transition,
62
+ but only the bang(!)-version will call <tt>save!</tt>. The <tt>can_discontinue?</tt> method will
63
+ not modify state but instead returns a boolean letting you know if a given transition is possible.
64
+
65
+ ==== Automatic scope generation
63
66
 
64
67
  <tt>transitions</tt> will automatically generate scopes for you if you are using ActiveRecord and tell it to do so via the <tt>auto_scopes</tt> option:
65
68
 
@@ -82,7 +85,7 @@ you can use this feature a la:
82
85
  >> Order.pick_line_items
83
86
  => [#<Order id: 3, state: "pick_line_items", description: nil, created_at: "2011-08-23 15:48:46", updated_at: "2011-08-23 15:48:46">]
84
87
 
85
- == Using <tt>on_transition</tt>
88
+ ==== Using <tt>on_transition</tt>
86
89
 
87
90
  Each event definition takes an optional "on_transition" argument, which allows you to execute methods on transition.
88
91
  You can pass in a Symbol, a String, a Proc or an Array containing method names as Symbol or String like this:
@@ -91,7 +94,7 @@ You can pass in a Symbol, a String, a Proc or an Array containing method names a
91
94
  transitions :to => :discontinued, :from => [:available, :out_of_stock], :on_transition => [:do_discontinue, :notify_clerk]
92
95
  end
93
96
 
94
- == Using <tt>success</tt>
97
+ ==== Using <tt>success</tt>
95
98
 
96
99
  In case you need to trigger a method call after a successful transition you can use <tt>success</tt>:
97
100
 
@@ -106,7 +109,7 @@ perfom some more complex success callbacks:
106
109
  transitions :to => :discontinued, :from => [:available, :out_of_stock]
107
110
  end
108
111
 
109
- == Timestamps
112
+ ==== Timestamps
110
113
 
111
114
  If you'd like to note the time of a state change, Transitions comes with timestamps free!
112
115
  To activate them, simply pass the :timestamp option to the event definition with a value of either true or
@@ -124,7 +127,7 @@ the name of the timestamp column.
124
127
  transitions :from => :exploded, :to => :rebuilt
125
128
  end
126
129
 
127
- == `event_fired` and `event_failed`
130
+ ==== Using <tt>event_fired</tt> and <tt>event_failed</tt>
128
131
 
129
132
  In case you define `event_fired` and / or `event_failed`, `transitions` will use those callbacks correspondingly.
130
133
  You can use those callbacks like this:
@@ -137,21 +140,24 @@ You can use those callbacks like this:
137
140
  MyLogger.warn "Event failed #{event.inspect}"
138
141
  end
139
142
 
140
- == Listing all the available states
143
+ ==== Listing all the available states
141
144
 
142
145
  You can easily get a listing of all available states:
143
146
 
144
147
  Order.available_states # Uses the <tt>default</tt> state machine
145
148
  # => [:pick_line_items, :picking_line_items]
146
149
 
147
- In case you have multiple state machines you can also pass the state machine name:
150
+ ==== Explicitly setting the initial state with the <tt>initial</tt> option
148
151
 
149
- Order.available_states(:your_machine)
152
+ state_machine :initial => :closed do
153
+ state :open
154
+ state :closed
155
+ end
150
156
 
151
- = Documentation, Guides & Examples
157
+ === Documentation, Guides & Examples
152
158
 
153
159
  - {Online API Documentation}[http://rdoc.info/github/troessner/transitions/master/Transitions]
154
160
 
155
- = Copyright
161
+ === Copyright
156
162
 
157
163
  Copyright (c) 2010 Jakub Kuźma, Timo Rößner. See LICENSE for details.
@@ -34,6 +34,10 @@ module Transitions
34
34
  machine.klass.send(:define_method, name.to_s) do |*args|
35
35
  machine.fire_event(name, self, false, *args)
36
36
  end
37
+
38
+ machine.klass.send(:define_method, "can_#{name.to_s}?") do |*args|
39
+ machine.events_for(current_state).include?(name.to_sym)
40
+ end
37
41
  end
38
42
  update(options, &block)
39
43
  end
@@ -43,6 +43,7 @@ module Transitions
43
43
  self
44
44
  end
45
45
 
46
+ # TODO Refactor me please?
46
47
  def fire_event(event, record, persist, *args)
47
48
  state_index[record.current_state].call_action(:exit, record)
48
49
  begin
@@ -70,17 +71,14 @@ module Transitions
70
71
  end
71
72
  end
72
73
 
73
- def states_for_select
74
- states.map { |st| [st.display_name, st.name.to_s] }
75
- end
76
-
77
74
  def events_for(state)
78
75
  events = @events.values.select { |event| event.transitions_from_state?(state) }
79
76
  events.map! { |event| event.name }
80
77
  end
81
78
 
82
79
  def current_state_variable
83
- "@current_state"
80
+ # TODO Refactor me away.
81
+ :@current_state
84
82
  end
85
83
 
86
84
  private
@@ -67,25 +67,8 @@ module Transitions
67
67
  private
68
68
  def define_state_query_method(machine)
69
69
  method_name, state_name = "#{@name}?", @name # Instance vars are out of scope when calling define_method below, so we use local variables.
70
- if method_already_defined_on_recipient?(machine, method_name)
71
- override_warning method_name
72
- else
73
- machine.klass.send :define_method, method_name do
74
- current_state.to_s == state_name.to_s
75
- end
76
- end
77
- end
78
-
79
- def method_already_defined_on_recipient?(machine, method_name)
80
- machine.klass.new.respond_to?(method_name)
81
- end
82
-
83
- def override_warning(method_name)
84
- warning = "Transitions: Can not define method #{method_name} because it is already defined, please rename either the existing method or the state."
85
- if Rails && Rails.logger
86
- Rails.logger.warn warning
87
- else
88
- puts warning
70
+ machine.klass.send :define_method, method_name do
71
+ current_state.to_s == state_name.to_s
89
72
  end
90
73
  end
91
74
  end
@@ -1,3 +1,3 @@
1
1
  module Transitions
2
- VERSION = "0.1.0"
2
+ VERSION = '0.1.1'
3
3
  end
@@ -1,38 +1,15 @@
1
1
  require "helper"
2
- require 'active_support/core_ext/module/aliasing'
3
-
4
- # TODO Tests here are quite messy, clean up.
5
-
6
- ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
7
2
 
8
3
  class CreateTrafficLights < ActiveRecord::Migration
9
4
  def self.up
10
- create_table(:traffic_lights) do |t|
5
+ create_table(:traffic_lights, :force => true) do |t|
11
6
  t.string :state
12
7
  t.string :name
13
8
  end
14
9
  end
15
10
  end
16
11
 
17
- class CreateLightBulbs < ActiveRecord::Migration
18
- def self.up
19
- create_table(:light_bulbs) do |t|
20
- t.string :state
21
- end
22
- end
23
- end
24
-
25
- class CreateLights < ActiveRecord::Migration
26
- def self.up
27
- create_table(:lights) do |t|
28
- t.string :state
29
- end
30
- end
31
- end
32
-
33
- CreateTrafficLights.migrate(:up)
34
- CreateLightBulbs.migrate(:up)
35
- CreateLights.migrate(:up)
12
+ set_up_db CreateTrafficLights
36
13
 
37
14
  class TrafficLight < ActiveRecord::Base
38
15
  include ActiveModel::Transitions
@@ -74,18 +51,9 @@ class ConditionalValidatingTrafficLight < TrafficLight
74
51
  validates(:name, :presence => true, :if => :red?)
75
52
  end
76
53
 
77
- class LightBulb < ActiveRecord::Base
78
- include ActiveModel::Transitions
79
-
80
- state_machine do
81
- state :off
82
- state :on
83
- end
84
- end
85
-
86
54
  class TestActiveRecord < Test::Unit::TestCase
87
55
  def setup
88
- create_database
56
+ set_up_db CreateTrafficLights
89
57
  @light = TrafficLight.create!
90
58
  end
91
59
 
@@ -94,6 +62,10 @@ class TestActiveRecord < Test::Unit::TestCase
94
62
  assert_equal "off", @light.state
95
63
  end
96
64
 
65
+ test "new active records defaults current state to the initial state" do
66
+ assert_equal :off, @light.current_state
67
+ end
68
+
97
69
  test "states initial state" do
98
70
  assert @light.off?
99
71
  assert_equal :off, @light.current_state
@@ -174,67 +146,4 @@ class TestActiveRecord < Test::Unit::TestCase
174
146
  assert_equal "green", @light.state
175
147
  assert_equal "red", @light.reload.state
176
148
  end
177
-
178
- end
179
-
180
- class TestNewActiveRecord < TestActiveRecord
181
-
182
- def setup
183
- create_database
184
- @light = TrafficLight.new
185
- end
186
-
187
- test "new active records defaults current state to the initial state" do
188
- assert_equal :off, @light.current_state
189
- end
190
-
191
- end
192
-
193
- class CreateBunnies < ActiveRecord::Migration
194
- def self.up
195
- create_table(:bunnies) do |t|
196
- t.string :state
197
- end
198
- end
199
- end
200
-
201
- CreateBunnies.migrate(:up)
202
-
203
- class Bunny < ActiveRecord::Base
204
- include ActiveModel::Transitions
205
-
206
- state_machine :auto_scopes => true do
207
- state :hobbling
208
- end
209
- end
210
-
211
- class TestScopes < Test::Unit::TestCase
212
- def setup
213
- create_database
214
- @bunny = Bunny.create!
215
- end
216
-
217
- test "scopes exist" do
218
- assert_respond_to Bunny, :hobbling
219
- end
220
-
221
- test "scope returns correct object" do
222
- assert_equal Bunny.hobbling.first, @bunny
223
- end
224
-
225
- test 'scopes are only generated if we explicitly say so' do
226
- assert_not_respond_to LightBulb, :off
227
- end
228
-
229
- test 'scope generation raises an exception if we try to overwrite an existing method' do
230
- assert_raise(Transitions::InvalidMethodOverride) {
231
- class TrafficLight < ActiveRecord::Base
232
- include ActiveModel::Transitions
233
-
234
- state_machine :auto_scopes => true do
235
- state :new
236
- end
237
- end
238
- }
239
- end
240
149
  end
@@ -0,0 +1,74 @@
1
+ require "helper"
2
+
3
+ class CreateBears < ActiveRecord::Migration
4
+ def self.up
5
+ create_table(:bears, :force => true) do |t|
6
+ t.string :state
7
+ end
8
+ end
9
+ end
10
+
11
+ class CreatePuppies < ActiveRecord::Migration
12
+ def self.up
13
+ create_table(:puppies, :force => true) do |t|
14
+ t.string :state
15
+ end
16
+ end
17
+ end
18
+
19
+ class CreateBunnies < ActiveRecord::Migration
20
+ def self.up
21
+ create_table(:bunnies, :force => true) do |t|
22
+ t.string :state
23
+ end
24
+ end
25
+ end
26
+
27
+ set_up_db CreateBunnies, CreatePuppies
28
+
29
+ class Bunny < ActiveRecord::Base
30
+ include ActiveModel::Transitions
31
+
32
+ state_machine :auto_scopes => true do
33
+ state :hobbling
34
+ end
35
+ end
36
+
37
+ class Puppy < ActiveRecord::Base
38
+ include ActiveModel::Transitions
39
+
40
+ state_machine do
41
+ state :barking
42
+ end
43
+ end
44
+
45
+ class TestScopes < Test::Unit::TestCase
46
+ def setup
47
+ set_up_db CreateBears, CreateBunnies, CreatePuppies
48
+ @bunny = Bunny.create!
49
+ end
50
+
51
+ test "scopes exist" do
52
+ assert_respond_to Bunny, :hobbling
53
+ end
54
+
55
+ test "scope returns correct object" do
56
+ assert_equal Bunny.hobbling.first, @bunny
57
+ end
58
+
59
+ test 'scopes are only generated if we explicitly say so' do
60
+ assert_not_respond_to Puppy, :barking
61
+ end
62
+
63
+ test 'scope generation raises an exception if we try to overwrite an existing method' do
64
+ assert_raise(Transitions::InvalidMethodOverride) {
65
+ class Bear < ActiveRecord::Base
66
+ include ActiveModel::Transitions
67
+
68
+ state_machine :auto_scopes => true do
69
+ state :new
70
+ end
71
+ end
72
+ }
73
+ end
74
+ end
@@ -1,7 +1,19 @@
1
1
  require "helper"
2
- require 'active_support/core_ext/module/aliasing'
3
2
 
4
- create_database
3
+ class CreateOrders < ActiveRecord::Migration
4
+ def self.up
5
+ create_table(:orders, :force => true) do |t|
6
+ t.string :state
7
+ t.string :order_number
8
+ t.datetime :paid_at
9
+ t.datetime :prepared_on
10
+ t.datetime :dispatched_at
11
+ t.date :cancellation_date
12
+ end
13
+ end
14
+ end
15
+
16
+ set_up_db CreateOrders
5
17
 
6
18
  class Order < ActiveRecord::Base
7
19
  include ActiveModel::Transitions
@@ -43,19 +55,16 @@ class Order < ActiveRecord::Base
43
55
  event :reopen, :timestamp => true do
44
56
  transitions :from => :cancelled, :to => :opened
45
57
  end
46
-
47
58
  end
48
59
  end
49
60
 
50
-
51
61
  class TestActiveRecordTimestamps < Test::Unit::TestCase
52
-
53
62
  require "securerandom"
54
-
63
+
55
64
  def setup
56
- create_database
65
+ set_up_db CreateOrders
57
66
  end
58
-
67
+
59
68
  def create_order(state = nil)
60
69
  Order.create! :order_number => SecureRandom.hex(4), :state => state
61
70
  end
@@ -114,5 +123,4 @@ class TestActiveRecordTimestamps < Test::Unit::TestCase
114
123
  end
115
124
  end
116
125
  end
117
-
118
126
  end
File without changes
@@ -0,0 +1,34 @@
1
+ require "helper"
2
+
3
+ class ChecksTestSubject
4
+ include Transitions
5
+
6
+ state_machine :initial => :initial do
7
+ state :initial
8
+ state :opened
9
+ state :closed
10
+
11
+ event :open do
12
+ transitions :from => :initial, :to => :opened
13
+ end
14
+
15
+ event :close do
16
+ transitions :from => :opened, :to => :closed
17
+ end
18
+ end
19
+ end
20
+
21
+ class StateMachineChecksTest < Test::Unit::TestCase
22
+ test "checks if a given transition is possible" do
23
+ subject = ChecksTestSubject.new
24
+ assert_equal :initial, subject.current_state
25
+ assert_equal true, subject.can_open?
26
+ assert_equal false, subject.can_close?
27
+
28
+ subject.open
29
+
30
+ assert_equal false, subject.can_open?
31
+ assert_equal true, subject.can_close?
32
+ end
33
+ end
34
+
data/test/helper.rb CHANGED
@@ -1,16 +1,18 @@
1
- Bundler.require
2
- require "test/unit"
3
- require "active_support/all"
4
- require "active_record"
5
- require "mocha"
6
- require "db/create_db"
1
+ require 'test/unit'
2
+ require 'active_record'
7
3
 
8
- require "transitions"
9
- require "active_model/transitions"
4
+ require 'transitions'
5
+ require 'active_model/transitions'
6
+
7
+ require 'mocha'
10
8
  require 'random_data'
11
9
 
12
- def create_database
13
- ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
10
+ def db_defaults!
11
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
14
12
  ActiveRecord::Migration.verbose = false
15
- CreateDb.migrate(:up)
13
+ end
14
+
15
+ def set_up_db(*migrations)
16
+ db_defaults!
17
+ migrations.each { |klass| klass.send :migrate, :up }
16
18
  end
@@ -11,7 +11,7 @@ class Bender
11
11
  end
12
12
 
13
13
  class TestAvailableStatesListing < Test::Unit::TestCase
14
- test 'available_states should return the states for the default state machine if no state machine is specified' do
14
+ test 'available_states should return the states for the state machine' do
15
15
  assert_equal [:drinking, :gambling, :smoking], Bender.available_states
16
16
  end
17
17
  end
@@ -31,4 +31,8 @@ class TransitionsMachineTest < Test::Unit::TestCase
31
31
  assert events.include?(:shutdown)
32
32
  assert events.include?(:timeout)
33
33
  end
34
+
35
+ test "test fire_event" do
36
+ pend "Implement me"
37
+ end
34
38
  end
@@ -2,15 +2,14 @@ require "helper"
2
2
 
3
3
  class TestState < Test::Unit::TestCase
4
4
  def setup
5
- @state_test_subject = Class.new do
5
+ machine = Class.new do
6
6
  include Transitions
7
7
  state_machine do
8
8
  end
9
- end
10
- @state_name = :astate
11
- @machine = @state_test_subject.state_machine
12
- @options = { :machine => @machine, :custom_key => :my_key }
13
- @state = Transitions::State.new(@state_name, @options)
9
+ end.get_state_machine
10
+ state_name = :astate
11
+ @options = { :machine => machine, :custom_key => :my_key }
12
+ @state = Transitions::State.new(state_name, @options)
14
13
  end
15
14
 
16
15
  def new_state_name
@@ -70,32 +69,3 @@ class TestState < Test::Unit::TestCase
70
69
  state.call_action(:entering, record)
71
70
  end
72
71
  end
73
-
74
- class StateOverrideMethodTestSubject
75
- include Transitions
76
-
77
- state_machine do
78
- end
79
-
80
- def a_state_name?; :foo; end
81
- end
82
-
83
-
84
- class TestStateQueryOverrideMethod < Test::Unit::TestCase
85
- def setup
86
- @state_name = 'a_state_name'
87
- @machine = StateOverrideMethodTestSubject.state_machine
88
- @options = { :machine => @machine }
89
- end
90
-
91
- test "warn on creation when we try to overwrite an existing method" do
92
- # TODO
93
- end
94
-
95
- test "should not override an already existing method" do
96
- Transitions::State.new :dummy, @options
97
- expected_result = :foo
98
- actual_result = StateOverrideMethodTestSubject.new.a_state_name?
99
- assert_equal expected_result, actual_result
100
- end
101
- end
@@ -0,0 +1,20 @@
1
+ require "helper"
2
+
3
+ class Bus
4
+ include Transitions
5
+
6
+ state_machine do
7
+ state :parking
8
+ end
9
+ end
10
+
11
+ class TestStatePredicateMethod < Test::Unit::TestCase
12
+ def setup
13
+ @bus = Bus.new
14
+ end
15
+
16
+ test "should generate predicate methods for states" do
17
+ assert_true @bus.respond_to?(:parking?)
18
+ assert_true @bus.send(:parking?)
19
+ end
20
+ end
@@ -0,0 +1,36 @@
1
+ require 'helper'
2
+
3
+ class Car
4
+ include Transitions
5
+
6
+ state_machine do
7
+ state :parked
8
+ state :driving
9
+ state :switched_off
10
+
11
+ event :start_driving do
12
+ transitions :from => :parked, :to => :driving
13
+ end
14
+
15
+ event :switch_off_engine do
16
+ transitions :from => :parked, :to => :switched_off
17
+ end
18
+ end
19
+ end
20
+
21
+ class TestStateTransitionEventFailedCallback < Test::Unit::TestCase
22
+ def setup
23
+ @car = Car.new
24
+ end
25
+
26
+ test "should execute the event_failed_callback and don't raise error if callback is defined" do
27
+ @car.start_driving
28
+ @car.expects(:event_failed).with(:switch_off_engine)
29
+ @car.switch_off_engine
30
+ end
31
+
32
+ test "should just re-raise any error on transition if the event_failed_callback isn't defined" do
33
+ @car.start_driving
34
+ assert_raise(Transitions::InvalidTransition) { @car.switch_off_engine }
35
+ end
36
+ end
@@ -0,0 +1,44 @@
1
+ require 'helper'
2
+
3
+ class Car
4
+ include Transitions
5
+
6
+ state_machine do
7
+ state :parked
8
+ state :driving
9
+
10
+ event :start_driving do
11
+ transitions :from => :parked, :to => :driving
12
+ end
13
+ end
14
+ end
15
+
16
+ class TestStateTransitionEventFiredCallback < Test::Unit::TestCase
17
+ def setup
18
+ @car = Car.new
19
+ end
20
+
21
+ test "should execute the event_fired callback after successfull event execution if it callback is defined" do
22
+ @car.stubs(:event_fired)
23
+ @car.expects(:event_fired).with(:parked, :driving, :start_driving).once
24
+
25
+ @car.start_driving!
26
+ end
27
+
28
+ test "should not execute the event_fired callback after successfull event execution if it callback is not defined" do
29
+ pend 'Test fails right now although functionality is working as expected'
30
+ # This test fails right now even though it works as expected in the console.
31
+ # The reason for this is, that mocha's `expects` does a little bit more than just set up an expectation,
32
+ # it actually defines this method if it doesn't exist or at least it overwrites respond_to?
33
+ # @car.respond_to?(:event_fired)
34
+ # returns false before the `expects` call, but true after.
35
+ # Hence, this test fails.
36
+ # Something like
37
+ # @car.instance_eval { undef :event_fired }
38
+ # doesn't work either, probably because expects just overwrites respond_to?
39
+ # but does not define the method
40
+ # How to fix?
41
+ @car.expects(:event_fired).never
42
+ @car.start_driving!
43
+ end
44
+ end
@@ -17,9 +17,6 @@ class Car
17
17
  end
18
18
  end
19
19
 
20
- def event_fired(current_state, new_state, event)
21
- end
22
-
23
20
  %w!start_engine loosen_handbrake push_gas_pedal!.each do |m|
24
21
  define_method(m){}
25
22
  end
@@ -43,9 +40,4 @@ class TestStateTransitionCallbacks < Test::Unit::TestCase
43
40
  @car.expects(:push_gas_pedal).in_sequence(on_transition_sequence)
44
41
  @car.start_driving!
45
42
  end
46
-
47
- test "should pass event when calling event_fired_callback" do
48
- @car.expects(:event_fired).with(:parked, :driving, :start_driving)
49
- @car.start_driving!
50
- end
51
43
  end
@@ -46,15 +46,4 @@ class TestStateTransitionSuccessCallback < Test::Unit::TestCase
46
46
  @car.expects(:loosen_handbrake).raises("Drive with handbrake fail!")
47
47
  @car.start_driving!
48
48
  end
49
-
50
- test "should execute the event_failed_callback and don't raise error if callback is defined" do
51
- @car.start_driving
52
- @car.expects(:event_failed).with(:switch_off_engine)
53
- @car.switch_off_engine
54
- end
55
-
56
- test "should just re-raise any error on transition if the event_failed_callback isn't defined" do
57
- @car.start_driving
58
- assert_raise(Transitions::InvalidTransition) { @car.switch_off_engine }
59
- end
60
49
  end
data/transitions.gemspec CHANGED
@@ -15,8 +15,8 @@ Gem::Specification.new do |s|
15
15
  s.rubyforge_project = "transitions"
16
16
 
17
17
  s.add_development_dependency "bundler", "~> 1"
18
- s.add_development_dependency "test-unit", "~> 2.2"
19
- s.add_development_dependency "mocha"
18
+ s.add_development_dependency "test-unit", "~> 2.5"
19
+ s.add_development_dependency "mocha", '~> 0.11.0' # With mocha 0.12 we get: undefined method `run' for #<StateMachineMachineTest:0x94918b8> (NoMethodError)
20
20
  s.add_development_dependency "rake"
21
21
  s.add_development_dependency "random_data"
22
22
  s.add_development_dependency "sqlite3"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: transitions
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-06-06 00:00:00.000000000 Z
13
+ date: 2012-08-06 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -35,7 +35,7 @@ dependencies:
35
35
  requirements:
36
36
  - - ~>
37
37
  - !ruby/object:Gem::Version
38
- version: '2.2'
38
+ version: '2.5'
39
39
  type: :development
40
40
  prerelease: false
41
41
  version_requirements: !ruby/object:Gem::Requirement
@@ -43,23 +43,23 @@ dependencies:
43
43
  requirements:
44
44
  - - ~>
45
45
  - !ruby/object:Gem::Version
46
- version: '2.2'
46
+ version: '2.5'
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: mocha
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
- - - ! '>='
52
+ - - ~>
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: 0.11.0
55
55
  type: :development
56
56
  prerelease: false
57
57
  version_requirements: !ruby/object:Gem::Requirement
58
58
  none: false
59
59
  requirements:
60
- - - ! '>='
60
+ - - ~>
61
61
  - !ruby/object:Gem::Version
62
- version: '0'
62
+ version: 0.11.0
63
63
  - !ruby/object:Gem::Dependency
64
64
  name: rake
65
65
  requirement: !ruby/object:Gem::Requirement
@@ -146,20 +146,24 @@ files:
146
146
  - lib/transitions/state.rb
147
147
  - lib/transitions/state_transition.rb
148
148
  - lib/transitions/version.rb
149
- - test/db/create_db.rb
149
+ - test/active_record/test_active_record.rb
150
+ - test/active_record/test_active_record_scopes.rb
151
+ - test/active_record/test_active_record_timestamps.rb
152
+ - test/event/test_event.rb
153
+ - test/event/test_event_arguments.rb
154
+ - test/event/test_event_being_fired.rb
155
+ - test/event/test_event_checks.rb
150
156
  - test/helper.rb
151
- - test/test_active_record.rb
152
- - test/test_active_record_timestamps.rb
153
- - test/test_available_states_listing.rb
154
- - test/test_event.rb
155
- - test/test_event_arguments.rb
156
- - test/test_event_being_fired.rb
157
- - test/test_machine.rb
158
- - test/test_state.rb
159
- - test/test_state_transition.rb
160
- - test/test_state_transition_callbacks.rb
161
- - test/test_state_transition_guard_check.rb
162
- - test/test_state_transition_success_callback.rb
157
+ - test/machine/test_available_states_listing.rb
158
+ - test/machine/test_machine.rb
159
+ - test/state/test_state.rb
160
+ - test/state/test_state_predicate_method.rb
161
+ - test/state_transition/test_state_transition.rb
162
+ - test/state_transition/test_state_transition_event_failed_callback.rb
163
+ - test/state_transition/test_state_transition_event_fired_callback.rb
164
+ - test/state_transition/test_state_transition_guard_check.rb
165
+ - test/state_transition/test_state_transition_on_transition_callback.rb
166
+ - test/state_transition/test_state_transition_success_callback.rb
163
167
  - transitions.gemspec
164
168
  homepage: http://github.com/troessner/transitions
165
169
  licenses: []
@@ -175,7 +179,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
175
179
  version: '0'
176
180
  segments:
177
181
  - 0
178
- hash: -659970477
182
+ hash: -930958051
179
183
  required_rubygems_version: !ruby/object:Gem::Requirement
180
184
  none: false
181
185
  requirements:
data/test/db/create_db.rb DELETED
@@ -1,22 +0,0 @@
1
- # Use this schema to create all required tables
2
- class CreateDb < ActiveRecord::Migration
3
- def self.up
4
- create_table(:traffic_lights, :force => true) do |t|
5
- t.string :state
6
- t.string :name
7
- end
8
- create_table(:bunnies, :force => true) do |t|
9
- t.string :state
10
- end
11
-
12
- create_table(:orders, :force => true) do |t|
13
- t.string :state
14
- t.string :order_number
15
- t.datetime :paid_at
16
- t.datetime :prepared_on
17
- t.datetime :dispatched_at
18
- t.date :cancellation_date
19
- end
20
-
21
- end
22
- end