transitions 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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