transitions 0.0.12 → 0.0.13
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +18 -3
- data/README.rdoc +45 -42
- data/lib/transitions/event.rb +10 -2
- data/lib/transitions/machine.rb +18 -12
- data/lib/transitions/version.rb +1 -1
- data/lib/transitions.rb +4 -0
- data/test/helper.rb +1 -0
- data/test/test_active_record.rb +73 -1
- data/test/test_available_states_listing.rb +27 -0
- data/test/test_event.rb +24 -5
- data/test/test_state_transition_success_callback.rb +60 -0
- data/transitions.gemspec +2 -1
- metadata +27 -15
- data/test/test_scopes.rb +0 -104
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
transitions (0.0.
|
4
|
+
transitions (0.0.13)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: http://rubygems.org/
|
@@ -16,15 +16,29 @@ GEM
|
|
16
16
|
arel (~> 1.0.0)
|
17
17
|
tzinfo (~> 0.3.23)
|
18
18
|
activesupport (3.0.0)
|
19
|
+
archive-tar-minitar (0.5.2)
|
19
20
|
arel (1.0.1)
|
20
21
|
activesupport (~> 3.0.0)
|
21
22
|
builder (2.1.2)
|
23
|
+
columnize (0.3.4)
|
22
24
|
i18n (0.4.1)
|
25
|
+
linecache19 (0.5.12)
|
26
|
+
ruby_core_source (>= 0.1.4)
|
23
27
|
mocha (0.9.8)
|
24
28
|
rake
|
25
29
|
rake (0.8.7)
|
30
|
+
ruby-debug-base19 (0.11.25)
|
31
|
+
columnize (>= 0.3.1)
|
32
|
+
linecache19 (>= 0.5.11)
|
33
|
+
ruby_core_source (>= 0.1.4)
|
34
|
+
ruby-debug19 (0.11.6)
|
35
|
+
columnize (>= 0.3.1)
|
36
|
+
linecache19 (>= 0.5.11)
|
37
|
+
ruby-debug-base19 (>= 0.11.19)
|
38
|
+
ruby_core_source (0.1.5)
|
39
|
+
archive-tar-minitar (>= 0.5.2)
|
26
40
|
sqlite3-ruby (1.3.1)
|
27
|
-
test-unit (2.
|
41
|
+
test-unit (2.4.1)
|
28
42
|
tzinfo (0.3.23)
|
29
43
|
|
30
44
|
PLATFORMS
|
@@ -34,6 +48,7 @@ DEPENDENCIES
|
|
34
48
|
activerecord (~> 3)
|
35
49
|
bundler (~> 1)
|
36
50
|
mocha
|
51
|
+
ruby-debug19
|
37
52
|
sqlite3-ruby
|
38
|
-
test-unit (~> 2)
|
53
|
+
test-unit (~> 2.2)
|
39
54
|
transitions!
|
data/README.rdoc
CHANGED
@@ -1,12 +1,28 @@
|
|
1
|
-
|
1
|
+
= Travis Build Status
|
2
2
|
|
3
|
-
=
|
3
|
+
{<img src="https://secure.travis-ci.org/troessner/transitions.png"/>}[http://travis-ci.org/troessner/transitions]
|
4
4
|
|
5
|
-
|
6
|
-
ActiveModel::StateMachine. It was extracted from ActiveModel and turned
|
7
|
-
into a gem when it got the axe in commit {db49c706b}[http://github.com/rails/rails/commit/db49c706b62e7ea2ab93f05399dbfddf5087ee0c].
|
5
|
+
= Synopsis
|
8
6
|
|
9
|
-
|
7
|
+
`transitions` is a ruby state machine implementation.
|
8
|
+
|
9
|
+
= Installation
|
10
|
+
|
11
|
+
== Rails
|
12
|
+
|
13
|
+
This goes into your Gemfile:
|
14
|
+
|
15
|
+
gem "transitions", :require => ["transitions", "active_record/transitions"]
|
16
|
+
|
17
|
+
… and this into your AR model:
|
18
|
+
|
19
|
+
include ActiveRecord::Transitions
|
20
|
+
|
21
|
+
== Standalone
|
22
|
+
|
23
|
+
gem install transitions
|
24
|
+
|
25
|
+
= Using transitions
|
10
26
|
|
11
27
|
require 'transitions'
|
12
28
|
|
@@ -30,6 +46,15 @@ into a gem when it got the axe in commit {db49c706b}[http://github.com/rails/rai
|
|
30
46
|
end
|
31
47
|
end
|
32
48
|
|
49
|
+
= Features
|
50
|
+
|
51
|
+
== Events
|
52
|
+
|
53
|
+
When you declare an event, say <tt>discontinue</tt>, two methods are declared for
|
54
|
+
you: <tt>discontinue</tt> and <tt>discontinue!</tt>. Both events will call
|
55
|
+
<tt>write_state_without_persistence</tt> on successful transition, but only the
|
56
|
+
bang(!)-version will call <tt>write_state</tt>.
|
57
|
+
|
33
58
|
== Automatic scope generation
|
34
59
|
|
35
60
|
`transitions` will automatically generate scopes for you if you are using ActiveRecord and tell it to do so via the `auto_scopes` option:
|
@@ -70,6 +95,12 @@ In case you need to trigger a method call after a successful transition you can
|
|
70
95
|
transitions :to => :discontinued, :from => [:available, :out_of_stock]
|
71
96
|
end
|
72
97
|
|
98
|
+
In addition to just specify the method name on the record as a symbol you can pass a lambda to
|
99
|
+
perfom some more complex success callbacks:
|
100
|
+
|
101
|
+
event :discontinue, :success => lambda { |order) AdminNotifier.notify_about_discontinued_order(order) } do
|
102
|
+
transitions :to => :discontinued, :from => [:available, :out_of_stock]
|
103
|
+
end
|
73
104
|
|
74
105
|
== Timestamps
|
75
106
|
|
@@ -89,52 +120,24 @@ the name of the timestamp column.
|
|
89
120
|
transiions :from => :exploded, :to => :rebuilt
|
90
121
|
end
|
91
122
|
|
123
|
+
== Listing all the available states
|
92
124
|
|
93
|
-
|
94
|
-
|
95
|
-
This goes into your Gemfile:
|
96
|
-
|
97
|
-
gem "transitions", :require => ["transitions", "active_record/transitions"]
|
98
|
-
|
99
|
-
… and this into your AR model:
|
100
|
-
|
101
|
-
include ActiveRecord::Transitions
|
102
|
-
|
103
|
-
=== A note about persistence
|
104
|
-
The property used to persist the models’ state is named <tt>state</tt> (really!),
|
105
|
-
which should be a string column wide enough to fit your longest state name.
|
106
|
-
It should also be mentioned that <tt>#save!</tt> is called after every successful event.
|
107
|
-
|
108
|
-
== Event execution flow
|
125
|
+
You can easily get a listing of all available states:
|
109
126
|
|
110
|
-
|
111
|
-
|
127
|
+
Order.available_states # Uses the `default` state machine
|
128
|
+
# => [:pick_line_items, :picking_line_items]
|
112
129
|
|
113
|
-
|
114
|
-
2. call <tt>:exit</tt> handler of <tt>:available</tt> state
|
115
|
-
3. call <tt>:guard</tt> of <tt>:available to :discontinue</tt> transition within <tt>#discontinue</tt> event
|
116
|
-
4. call <tt>#event_failed(:event)</tt> and abort unless <tt>3.</tt> returned <tt>true</tt>
|
117
|
-
5. call <tt>:on_transition(:reason => :pirates)</tt> of <tt>:available to :discontinue</tt> transition within <tt>#discontinue</tt> event
|
118
|
-
6. call <tt>:enter</tt> handler of <tt>:discontinue</tt>
|
119
|
-
7. call <tt>#event_fired(:available, :discontinue)</tt>
|
120
|
-
8. call <tt>#write_state(machine, :discontinue)</tt>
|
121
|
-
9. call <tt>#write_state_without_persistence(machine, :discontinue)</tt>
|
122
|
-
10. call <tt>baby_ninja#:success</tt> handler method of <tt>#discontinue</tt> event
|
130
|
+
In case you have multiple state machines you can also pass the state machine name:
|
123
131
|
|
124
|
-
|
125
|
-
|
126
|
-
When you declare an event <tt>discontinue</tt>, two methods are declared for
|
127
|
-
you: <tt>discontinue</tt> and <tt>discontinue!</tt>. Both events will call
|
128
|
-
<tt>write_state_without_persistence</tt> on successful transition, but only the
|
129
|
-
bang(!)-version will call <tt>write_state</tt>.
|
132
|
+
Order.available_states(:your_machine)
|
130
133
|
|
131
|
-
|
134
|
+
= Documentation, Guides & Examples
|
132
135
|
|
133
136
|
- {Online API Documentation}[http://rdoc.info/github/troessner/transitions/master/Transitions]
|
134
137
|
- Krzysiek Heród (aka {Netizer}[http://github.com/netizer]) wrote a nice
|
135
138
|
{blog post}[http://dev.netizer.pl/transitions-state-machine-for-rails-3.html]
|
136
139
|
about using Transitions in ActiveRecord.
|
137
140
|
|
138
|
-
|
141
|
+
= Copyright
|
139
142
|
|
140
143
|
Copyright (c) 2010 Jakub Kuźma, Timo Rößner. See LICENSE for details.
|
data/lib/transitions/event.rb
CHANGED
@@ -74,7 +74,7 @@ module Transitions
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def update(options = {}, &block)
|
77
|
-
@success = options[:success] if options.key?(:success)
|
77
|
+
@success = build_sucess_callback(options[:success]) if options.key?(:success)
|
78
78
|
self.timestamp = options[:timestamp] if options[:timestamp]
|
79
79
|
instance_eval(&block) if block
|
80
80
|
self
|
@@ -118,12 +118,20 @@ module Transitions
|
|
118
118
|
Please define #{at_name} or #{on_name} in #{obj.class}"
|
119
119
|
end
|
120
120
|
end
|
121
|
-
|
122
121
|
|
123
122
|
def transitions(trans_opts)
|
124
123
|
Array(trans_opts[:from]).each do |s|
|
125
124
|
@transitions << StateTransition.new(trans_opts.merge({:from => s.to_sym}))
|
126
125
|
end
|
127
126
|
end
|
127
|
+
|
128
|
+
def build_sucess_callback(callback_symbol_or_proc)
|
129
|
+
case callback_symbol_or_proc
|
130
|
+
when Proc
|
131
|
+
callback_symbol_or_proc
|
132
|
+
when Symbol
|
133
|
+
lambda { |record| record.send(callback_symbol_or_proc) }
|
134
|
+
end
|
135
|
+
end
|
128
136
|
end
|
129
137
|
end
|
data/lib/transitions/machine.rb
CHANGED
@@ -45,22 +45,28 @@ module Transitions
|
|
45
45
|
|
46
46
|
def fire_event(event, record, persist, *args)
|
47
47
|
state_index[record.current_state(@name)].call_action(:exit, record)
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
record.
|
48
|
+
begin
|
49
|
+
if new_state = @events[event].fire(record, nil, *args)
|
50
|
+
state_index[new_state].call_action(:enter, record)
|
51
|
+
|
52
|
+
if record.respond_to?(event_fired_callback)
|
53
|
+
record.send(event_fired_callback, record.current_state, new_state, event)
|
54
|
+
end
|
55
|
+
|
56
|
+
record.current_state(@name, new_state, persist)
|
57
|
+
@events[event].success.call(record) if @events[event].success
|
58
|
+
return true
|
59
|
+
else
|
60
|
+
record.send(event_fired_callback, event) if record.respond_to?(event_failed_callback)
|
61
|
+
return false
|
53
62
|
end
|
54
|
-
|
55
|
-
record.current_state(@name, new_state, persist)
|
56
|
-
record.send(@events[event].success) if @events[event].success
|
57
|
-
true
|
58
|
-
else
|
63
|
+
rescue => e
|
59
64
|
if record.respond_to?(event_failed_callback)
|
60
65
|
record.send(event_failed_callback, event)
|
66
|
+
return false
|
67
|
+
else
|
68
|
+
raise e
|
61
69
|
end
|
62
|
-
|
63
|
-
false
|
64
70
|
end
|
65
71
|
end
|
66
72
|
|
data/lib/transitions/version.rb
CHANGED
data/lib/transitions.rb
CHANGED
@@ -54,6 +54,10 @@ module Transitions
|
|
54
54
|
block ? state_machines[name].update(options, &block) : state_machines[name]
|
55
55
|
end
|
56
56
|
|
57
|
+
def available_states name = :default
|
58
|
+
state_machines[name].states.map(&:name).sort
|
59
|
+
end
|
60
|
+
|
57
61
|
def define_state_query_method(state_name)
|
58
62
|
name = "#{state_name}?"
|
59
63
|
undef_method(name) if method_defined?(name)
|
data/test/helper.rb
CHANGED
data/test/test_active_record.rb
CHANGED
@@ -3,10 +3,39 @@ require 'active_support/core_ext/module/aliasing'
|
|
3
3
|
|
4
4
|
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
5
5
|
|
6
|
+
class CreateTrafficLights < ActiveRecord::Migration
|
7
|
+
def self.up
|
8
|
+
create_table(:traffic_lights) do |t|
|
9
|
+
t.string :state
|
10
|
+
t.string :name
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class CreateLightBulbs < ActiveRecord::Migration
|
16
|
+
def self.up
|
17
|
+
create_table(:light_bulbs) do |t|
|
18
|
+
t.string :state
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class CreateLights < ActiveRecord::Migration
|
24
|
+
def self.up
|
25
|
+
create_table(:lights) do |t|
|
26
|
+
t.string :state
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
CreateTrafficLights.migrate(:up)
|
32
|
+
CreateLightBulbs.migrate(:up)
|
33
|
+
CreateLights.migrate(:up)
|
34
|
+
|
6
35
|
class TrafficLight < ActiveRecord::Base
|
7
36
|
include ActiveRecord::Transitions
|
8
37
|
|
9
|
-
state_machine do
|
38
|
+
state_machine :auto_scopes => true do
|
10
39
|
state :off
|
11
40
|
|
12
41
|
state :red
|
@@ -43,6 +72,15 @@ class ConditionalValidatingTrafficLight < TrafficLight
|
|
43
72
|
validates(:name, :presence => true, :if => :red?)
|
44
73
|
end
|
45
74
|
|
75
|
+
class LightBulb < ActiveRecord::Base
|
76
|
+
include ActiveRecord::Transitions
|
77
|
+
|
78
|
+
state_machine do
|
79
|
+
state :off
|
80
|
+
state :on
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
46
84
|
class TestActiveRecord < Test::Unit::TestCase
|
47
85
|
def setup
|
48
86
|
create_database
|
@@ -141,3 +179,37 @@ class TestNewActiveRecord < TestActiveRecord
|
|
141
179
|
end
|
142
180
|
|
143
181
|
end
|
182
|
+
|
183
|
+
class TestScopes < Test::Unit::TestCase
|
184
|
+
test "scope returns correct object" do
|
185
|
+
@light = TrafficLight.create!
|
186
|
+
assert_respond_to TrafficLight, :off
|
187
|
+
assert_equal TrafficLight.off.first, @light
|
188
|
+
assert TrafficLight.red.empty?
|
189
|
+
end
|
190
|
+
|
191
|
+
test "scopes exist" do
|
192
|
+
assert_respond_to TrafficLight, :off
|
193
|
+
assert_respond_to TrafficLight, :red
|
194
|
+
assert_respond_to TrafficLight, :green
|
195
|
+
assert_respond_to TrafficLight, :yellow
|
196
|
+
end
|
197
|
+
|
198
|
+
test 'scopes are only generated if we explicitly say so' do
|
199
|
+
assert_not_respond_to LightBulb, :off
|
200
|
+
assert_not_respond_to LightBulb, :on
|
201
|
+
end
|
202
|
+
|
203
|
+
test 'scope generation raises an exception if we try to overwrite an existing method' do
|
204
|
+
assert_raise(Transitions::InvalidMethodOverride) {
|
205
|
+
class Light < ActiveRecord::Base
|
206
|
+
include ActiveRecord::Transitions
|
207
|
+
|
208
|
+
state_machine :auto_scopes => true do
|
209
|
+
state :new
|
210
|
+
state :broken
|
211
|
+
end
|
212
|
+
end
|
213
|
+
}
|
214
|
+
end
|
215
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class Bender
|
4
|
+
include Transitions
|
5
|
+
|
6
|
+
state_machine :default do
|
7
|
+
state :drinking
|
8
|
+
state :smoking
|
9
|
+
state :gambling
|
10
|
+
end
|
11
|
+
|
12
|
+
state_machine :maintenance do
|
13
|
+
state :wip
|
14
|
+
state :finished
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class TestAvailableStatesListing < Test::Unit::TestCase
|
19
|
+
test 'available_states should return the states for the default state machine if no state machine is specified' do
|
20
|
+
assert_equal [:drinking, :gambling, :smoking], Bender.available_states
|
21
|
+
end
|
22
|
+
|
23
|
+
test 'available_states should return the states for a given state' do
|
24
|
+
assert_equal [:finished, :wip], Bender.available_states(:maintenance)
|
25
|
+
assert_equal [:drinking, :gambling, :smoking], Bender.available_states(:default)
|
26
|
+
end
|
27
|
+
end
|
data/test/test_event.rb
CHANGED
@@ -3,11 +3,19 @@ require "helper"
|
|
3
3
|
class TestEvent < Test::Unit::TestCase
|
4
4
|
def setup
|
5
5
|
@state_name = :close_order
|
6
|
-
@
|
6
|
+
@success_as_symbol = :success_callback
|
7
|
+
@success_as_lambda = lambda { |record| record.success_callback }
|
7
8
|
end
|
8
9
|
|
9
|
-
def
|
10
|
-
@event = Transitions::Event.new(nil, @state_name, {:success => @
|
10
|
+
def event_with_symbol_success_callback
|
11
|
+
@event = Transitions::Event.new(nil, @state_name, {:success => @success_as_symbol}) do
|
12
|
+
transitions :to => :closed, :from => [:open, :received]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
alias_method :new_event, :event_with_symbol_success_callback
|
16
|
+
|
17
|
+
def event_with_lambda_success_callback
|
18
|
+
@event = Transitions::Event.new(nil, @state_name, {:success => @success_as_lambda}) do
|
11
19
|
transitions :to => :closed, :from => [:open, :received]
|
12
20
|
end
|
13
21
|
end
|
@@ -16,8 +24,19 @@ class TestEvent < Test::Unit::TestCase
|
|
16
24
|
assert_equal @state_name, new_event.name
|
17
25
|
end
|
18
26
|
|
19
|
-
test "should set the success
|
20
|
-
|
27
|
+
test "should set the success callback with a symbol and return a block" do
|
28
|
+
assert_respond_to event_with_symbol_success_callback.success, :call
|
29
|
+
end
|
30
|
+
|
31
|
+
test "should build a block which calls the given success_callback symbol on the passed record instance" do
|
32
|
+
record = mock("SomeRecordToGetCalled")
|
33
|
+
record.expects(:success_callback)
|
34
|
+
|
35
|
+
event_with_symbol_success_callback.success.call(record)
|
36
|
+
end
|
37
|
+
|
38
|
+
test "should set the success callback with a lambda" do
|
39
|
+
assert_respond_to event_with_lambda_success_callback.success, :call
|
21
40
|
end
|
22
41
|
|
23
42
|
test "should create StateTransitions" do
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class DrivingInstructor
|
4
|
+
def self.applause!
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
class DrivingSchoolCar
|
9
|
+
include Transitions
|
10
|
+
|
11
|
+
state_machine do
|
12
|
+
state :parked
|
13
|
+
state :running
|
14
|
+
state :driving
|
15
|
+
state :switched_off
|
16
|
+
|
17
|
+
event :start_driving, :success => lambda { |car| DrivingInstructor.applause! } do
|
18
|
+
transitions :from => :parked, :to => :driving, :on_transition => [:start_engine, :loosen_handbrake, :push_gas_pedal]
|
19
|
+
end
|
20
|
+
|
21
|
+
event :switch_off_engine do
|
22
|
+
transitions :from => :parked, :to => :switched_off
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
%w!start_engine loosen_handbrake push_gas_pedal!.each do |m|
|
27
|
+
define_method(m){}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class TestStateTransitionSuccessCallback < Test::Unit::TestCase
|
32
|
+
def setup
|
33
|
+
@car = DrivingSchoolCar.new
|
34
|
+
end
|
35
|
+
|
36
|
+
test "should execute the success callback after successfull event execution" do
|
37
|
+
DrivingInstructor.expects(:applause!)
|
38
|
+
|
39
|
+
@car.start_driving!
|
40
|
+
end
|
41
|
+
|
42
|
+
test "should not execute the success callback after event execution failed" do
|
43
|
+
DrivingInstructor.expects(:applause!).never
|
44
|
+
|
45
|
+
@car.stubs(:event_failed)
|
46
|
+
@car.expects(:loosen_handbrake).raises("Drive with handbrake fail!")
|
47
|
+
@car.start_driving!
|
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
|
+
end
|
data/transitions.gemspec
CHANGED
@@ -15,10 +15,11 @@ 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"
|
18
|
+
s.add_development_dependency "test-unit", "~> 2.2"
|
19
19
|
s.add_development_dependency "mocha"
|
20
20
|
s.add_development_dependency "sqlite3-ruby"
|
21
21
|
s.add_development_dependency "activerecord", "~> 3"
|
22
|
+
s.add_development_dependency "ruby-debug19"
|
22
23
|
|
23
24
|
s.files = `git ls-files`.split("\n")
|
24
25
|
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
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.0.
|
4
|
+
version: 0.0.13
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-12-20 00:00:00.000000000Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
17
|
-
requirement: &
|
17
|
+
requirement: &77702010 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ~>
|
@@ -22,21 +22,21 @@ dependencies:
|
|
22
22
|
version: '1'
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *77702010
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: test-unit
|
28
|
-
requirement: &
|
28
|
+
requirement: &77701310 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '2'
|
33
|
+
version: '2.2'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *77701310
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: mocha
|
39
|
-
requirement: &
|
39
|
+
requirement: &77700870 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ! '>='
|
@@ -44,10 +44,10 @@ dependencies:
|
|
44
44
|
version: '0'
|
45
45
|
type: :development
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *77700870
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: sqlite3-ruby
|
50
|
-
requirement: &
|
50
|
+
requirement: &77700370 !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
52
52
|
requirements:
|
53
53
|
- - ! '>='
|
@@ -55,10 +55,10 @@ dependencies:
|
|
55
55
|
version: '0'
|
56
56
|
type: :development
|
57
57
|
prerelease: false
|
58
|
-
version_requirements: *
|
58
|
+
version_requirements: *77700370
|
59
59
|
- !ruby/object:Gem::Dependency
|
60
60
|
name: activerecord
|
61
|
-
requirement: &
|
61
|
+
requirement: &77699800 !ruby/object:Gem::Requirement
|
62
62
|
none: false
|
63
63
|
requirements:
|
64
64
|
- - ~>
|
@@ -66,7 +66,18 @@ dependencies:
|
|
66
66
|
version: '3'
|
67
67
|
type: :development
|
68
68
|
prerelease: false
|
69
|
-
version_requirements: *
|
69
|
+
version_requirements: *77699800
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: ruby-debug19
|
72
|
+
requirement: &77698980 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: *77698980
|
70
81
|
description: Lightweight state machine extracted from ActiveModel
|
71
82
|
email: timo.roessner@googlemail.com
|
72
83
|
executables: []
|
@@ -92,15 +103,16 @@ files:
|
|
92
103
|
- test/helper.rb
|
93
104
|
- test/test_active_record.rb
|
94
105
|
- test/test_active_record_timestamps.rb
|
106
|
+
- test/test_available_states_listing.rb
|
95
107
|
- test/test_event.rb
|
96
108
|
- test/test_event_arguments.rb
|
97
109
|
- test/test_event_being_fired.rb
|
98
110
|
- test/test_machine.rb
|
99
|
-
- test/test_scopes.rb
|
100
111
|
- test/test_state.rb
|
101
112
|
- test/test_state_transition.rb
|
102
113
|
- test/test_state_transition_callbacks.rb
|
103
114
|
- test/test_state_transition_guard_check.rb
|
115
|
+
- test/test_state_transition_success_callback.rb
|
104
116
|
- transitions.gemspec
|
105
117
|
homepage: http://github.com/troessner/transitions
|
106
118
|
licenses: []
|
@@ -116,7 +128,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
116
128
|
version: '0'
|
117
129
|
segments:
|
118
130
|
- 0
|
119
|
-
hash:
|
131
|
+
hash: 819396333
|
120
132
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
133
|
none: false
|
122
134
|
requirements:
|
data/test/test_scopes.rb
DELETED
@@ -1,104 +0,0 @@
|
|
1
|
-
require "helper"
|
2
|
-
require 'active_support/core_ext/module/aliasing'
|
3
|
-
|
4
|
-
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
5
|
-
|
6
|
-
class CreateTrafficLights < ActiveRecord::Migration
|
7
|
-
def self.up
|
8
|
-
create_table(:traffic_lights) do |t|
|
9
|
-
t.string :state
|
10
|
-
t.string :name
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
class CreateLightBulbs < ActiveRecord::Migration
|
16
|
-
def self.up
|
17
|
-
create_table(:light_bulbs) do |t|
|
18
|
-
t.string :state
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
class CreateLights < ActiveRecord::Migration
|
24
|
-
def self.up
|
25
|
-
create_table(:lights) do |t|
|
26
|
-
t.string :state
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
CreateTrafficLights.migrate(:up)
|
32
|
-
CreateLightBulbs.migrate(:up)
|
33
|
-
CreateLights.migrate(:up)
|
34
|
-
|
35
|
-
class TrafficLight < ActiveRecord::Base
|
36
|
-
include ActiveRecord::Transitions
|
37
|
-
|
38
|
-
state_machine :auto_scopes => true do
|
39
|
-
state :off
|
40
|
-
|
41
|
-
state :red
|
42
|
-
state :green
|
43
|
-
state :yellow
|
44
|
-
|
45
|
-
event :red_on do
|
46
|
-
transitions :to => :red, :from => [:yellow]
|
47
|
-
end
|
48
|
-
|
49
|
-
event :green_on do
|
50
|
-
transitions :to => :green, :from => [:red]
|
51
|
-
end
|
52
|
-
|
53
|
-
event :yellow_on do
|
54
|
-
transitions :to => :yellow, :from => [:green]
|
55
|
-
end
|
56
|
-
|
57
|
-
event :reset do
|
58
|
-
transitions :to => :red, :from => [:off]
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
class LightBulb < ActiveRecord::Base
|
64
|
-
include ActiveRecord::Transitions
|
65
|
-
|
66
|
-
state_machine do
|
67
|
-
state :off
|
68
|
-
state :on
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
class TestScopes < Test::Unit::TestCase
|
73
|
-
test "scope returns correct object" do
|
74
|
-
@light = TrafficLight.create!
|
75
|
-
assert TrafficLight.respond_to? :off
|
76
|
-
assert_equal TrafficLight.off.first, @light
|
77
|
-
assert TrafficLight.red.empty?
|
78
|
-
end
|
79
|
-
|
80
|
-
test "scopes exist" do
|
81
|
-
assert TrafficLight.respond_to? :off
|
82
|
-
assert TrafficLight.respond_to? :red
|
83
|
-
assert TrafficLight.respond_to? :green
|
84
|
-
assert TrafficLight.respond_to? :yellow
|
85
|
-
end
|
86
|
-
|
87
|
-
test 'scopes are only generated if we explicitly say so' do
|
88
|
-
assert !LightBulb.respond_to?(:off)
|
89
|
-
assert !LightBulb.respond_to?(:on)
|
90
|
-
end
|
91
|
-
|
92
|
-
test 'scope generation raises an exception if we try to overwrite an existing method' do
|
93
|
-
assert_raise(Transitions::InvalidMethodOverride) {
|
94
|
-
class Light < ActiveRecord::Base
|
95
|
-
include ActiveRecord::Transitions
|
96
|
-
|
97
|
-
state_machine :auto_scopes => true do
|
98
|
-
state :new
|
99
|
-
state :broken
|
100
|
-
end
|
101
|
-
end
|
102
|
-
}
|
103
|
-
end
|
104
|
-
end
|