transitions 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +18 -1
- data/.travis.yml +5 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +7 -6
- data/LICENSE.txt +21 -0
- data/README.md +9 -4
- data/Rakefile +9 -4
- data/bin/console +7 -0
- data/lib/active_model/transitions.rb +19 -12
- data/lib/transitions.rb +15 -15
- data/lib/transitions/event.rb +19 -15
- data/lib/transitions/machine.rb +23 -22
- data/lib/transitions/presenter.rb +2 -6
- data/lib/transitions/state.rb +10 -7
- data/lib/transitions/state_transition.rb +37 -6
- data/lib/transitions/version.rb +1 -1
- data/transitions.gemspec +23 -24
- metadata +39 -45
- data/.ruby-gemset +0 -1
- data/MIT-LICENSE.txt +0 -21
- data/test/active_record/test_active_record.rb +0 -326
- data/test/active_record/test_active_record_scopes.rb +0 -64
- data/test/active_record/test_active_record_timestamps.rb +0 -132
- data/test/active_record/test_custom_select.rb +0 -33
- data/test/event/test_event.rb +0 -72
- data/test/event/test_event_arguments.rb +0 -29
- data/test/event/test_event_being_fired.rb +0 -26
- data/test/event/test_event_checks.rb +0 -33
- data/test/helper.rb +0 -18
- data/test/machine/machine_template.rb +0 -27
- data/test/machine/test_available_states_listing.rb +0 -24
- data/test/machine/test_fire_event_machine.rb +0 -29
- data/test/machine/test_machine.rb +0 -66
- data/test/state/test_state.rb +0 -71
- data/test/state/test_state_predicate_method.rb +0 -32
- data/test/state_transition/test_state_transition.rb +0 -45
- data/test/state_transition/test_state_transition_event_failed_callback.rb +0 -36
- data/test/state_transition/test_state_transition_event_fired_callback.rb +0 -44
- data/test/state_transition/test_state_transition_guard_check.rb +0 -66
- data/test/state_transition/test_state_transition_on_transition_callback.rb +0 -48
- data/test/state_transition/test_state_transition_success_callback.rb +0 -49
@@ -1,64 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
class CreateBunnies < ActiveRecord::Migration
|
4
|
-
def self.up
|
5
|
-
create_table(:bunnies, force: true) do |t|
|
6
|
-
t.string :status # Explicitly use another state column to ensure that this whole enchilada is working with other state column names than the default ones.
|
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 Bunny < ActiveRecord::Base
|
20
|
-
include ActiveModel::Transitions
|
21
|
-
|
22
|
-
state_machine attribute_name: :status, auto_scopes: true do
|
23
|
-
state :hobbling
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
class Puppy < ActiveRecord::Base
|
28
|
-
include ActiveModel::Transitions
|
29
|
-
|
30
|
-
state_machine do
|
31
|
-
state :barking
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
class TestScopes < Test::Unit::TestCase
|
36
|
-
def setup
|
37
|
-
set_up_db CreateBunnies, CreatePuppies
|
38
|
-
@bunny = Bunny.create!
|
39
|
-
end
|
40
|
-
|
41
|
-
test 'scopes exist' do
|
42
|
-
assert_respond_to Bunny, :hobbling
|
43
|
-
end
|
44
|
-
|
45
|
-
test 'scope returns correct object' do
|
46
|
-
assert_equal Bunny.hobbling.first, @bunny
|
47
|
-
end
|
48
|
-
|
49
|
-
test 'scopes are only generated if we explicitly say so' do
|
50
|
-
assert_not_respond_to Puppy, :barking
|
51
|
-
end
|
52
|
-
|
53
|
-
test 'scope generation raises an exception if we try to overwrite an existing method' do
|
54
|
-
assert_raise(Transitions::InvalidMethodOverride) do
|
55
|
-
Class.new(ActiveRecord::Base) do
|
56
|
-
include ActiveModel::Transitions
|
57
|
-
|
58
|
-
state_machine auto_scopes: true do
|
59
|
-
state :new
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
@@ -1,132 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
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
|
-
t.boolean :allow_transition, default: true
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
class Order < ActiveRecord::Base
|
18
|
-
include ActiveModel::Transitions
|
19
|
-
|
20
|
-
state_machine do
|
21
|
-
state :opened
|
22
|
-
state :placed
|
23
|
-
state :paid
|
24
|
-
state :prepared
|
25
|
-
state :delivered
|
26
|
-
state :cancelled
|
27
|
-
|
28
|
-
# no timestamp col is being specified here - should be ignored
|
29
|
-
event :place do
|
30
|
-
transitions from: :opened, to: :placed
|
31
|
-
end
|
32
|
-
|
33
|
-
# should set paid_at timestamp
|
34
|
-
event :pay, timestamp: true do
|
35
|
-
transitions from: :placed, to: :paid, guard: lambda { |obj| obj.allow_transition }
|
36
|
-
end
|
37
|
-
|
38
|
-
# should set prepared_on
|
39
|
-
event :prepare, timestamp: true do
|
40
|
-
transitions from: :paid, to: :prepared
|
41
|
-
end
|
42
|
-
|
43
|
-
# should set dispatched_at
|
44
|
-
event :deliver, timestamp: 'dispatched_at' do
|
45
|
-
transitions from: :prepared, to: :delivered
|
46
|
-
end
|
47
|
-
|
48
|
-
# should set cancellation_date
|
49
|
-
event :cancel, timestamp: :cancellation_date do
|
50
|
-
transitions from: [:placed, :paid, :prepared], to: :cancelled
|
51
|
-
end
|
52
|
-
|
53
|
-
# should raise an exception as there is no timestamp col
|
54
|
-
event :reopen, timestamp: true do
|
55
|
-
transitions from: :cancelled, to: :opened
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
class TestActiveRecordTimestamps < Test::Unit::TestCase
|
61
|
-
require 'securerandom'
|
62
|
-
|
63
|
-
def setup
|
64
|
-
set_up_db CreateOrders
|
65
|
-
end
|
66
|
-
|
67
|
-
def create_order(state = nil)
|
68
|
-
Order.create! order_number: SecureRandom.hex(4), state: state
|
69
|
-
end
|
70
|
-
|
71
|
-
# control case, no timestamp has been set so we should expect default behaviour
|
72
|
-
test 'moving to placed does not raise any exceptions' do
|
73
|
-
@order = create_order
|
74
|
-
assert_nothing_raised { @order.place! }
|
75
|
-
assert_equal @order.state, 'placed'
|
76
|
-
end
|
77
|
-
|
78
|
-
test 'moving to paid should set paid_at' do
|
79
|
-
@order = create_order(:placed)
|
80
|
-
@order.pay!
|
81
|
-
@order.reload
|
82
|
-
assert_not_nil @order.paid_at
|
83
|
-
end
|
84
|
-
|
85
|
-
test 'moving to paid should not set paid_at if our guard evaluates to false' do
|
86
|
-
@order = create_order(:placed)
|
87
|
-
@order.update_attribute :allow_transition, false
|
88
|
-
@order.pay!
|
89
|
-
@order.reload
|
90
|
-
assert_nil @order.paid_at
|
91
|
-
end
|
92
|
-
|
93
|
-
test 'moving to prepared should set prepared_on' do
|
94
|
-
@order = create_order(:paid)
|
95
|
-
@order.prepare!
|
96
|
-
@order.reload
|
97
|
-
assert_not_nil @order.prepared_on
|
98
|
-
end
|
99
|
-
|
100
|
-
test 'moving to delivered should set dispatched_at' do
|
101
|
-
@order = create_order(:prepared)
|
102
|
-
@order.deliver!
|
103
|
-
@order.reload
|
104
|
-
assert_not_nil @order.dispatched_at
|
105
|
-
end
|
106
|
-
|
107
|
-
test 'moving to cancelled should set cancellation_date' do
|
108
|
-
@order = create_order(:placed)
|
109
|
-
@order.cancel!
|
110
|
-
@order.reload
|
111
|
-
assert_not_nil @order.cancellation_date
|
112
|
-
end
|
113
|
-
|
114
|
-
test 'moving to reopened should raise an exception as there is no attribute' do
|
115
|
-
@order = create_order(:cancelled)
|
116
|
-
assert_raise(NoMethodError) { @order.re_open! }
|
117
|
-
@order.reload
|
118
|
-
end
|
119
|
-
|
120
|
-
test 'passing an invalid value to timestamp options should raise an exception' do
|
121
|
-
assert_raise(ArgumentError) do
|
122
|
-
class Order < ActiveRecord::Base
|
123
|
-
include ActiveModel::Transitions
|
124
|
-
state_machine do
|
125
|
-
event :replace, timestamp: 1 do
|
126
|
-
transitions from: :prepared, to: :placed
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
# Regression test for https://github.com/troessner/transitions/issues/95
|
4
|
-
class CreateSwitches < ActiveRecord::Migration
|
5
|
-
def self.up
|
6
|
-
create_table(:switches, force: true) do |t|
|
7
|
-
t.string :state
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
class Switch < ActiveRecord::Base
|
13
|
-
include ActiveModel::Transitions
|
14
|
-
|
15
|
-
state_machine do
|
16
|
-
state :off
|
17
|
-
state :on
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
class TestCustomSelect < Test::Unit::TestCase
|
22
|
-
def setup
|
23
|
-
set_up_db CreateSwitches
|
24
|
-
Switch.create!
|
25
|
-
end
|
26
|
-
|
27
|
-
test 'should not trigger an exception when we use a custom select query which excludes the name of our state attribute' do
|
28
|
-
result = Switch.select(:id)
|
29
|
-
assert_nothing_raised NoMethodError do
|
30
|
-
result.inspect
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
data/test/event/test_event.rb
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
class TestEvent < Test::Unit::TestCase
|
4
|
-
def setup
|
5
|
-
@state_name = :close_order
|
6
|
-
@success_as_symbol = :success_callback
|
7
|
-
@success_as_lambda = lambda { |record| record.success_callback }
|
8
|
-
@success_as_array = [@success_as_symbol, @success_as_lambda]
|
9
|
-
end
|
10
|
-
|
11
|
-
def event_with_symbol_success_callback
|
12
|
-
@event = Transitions::Event.new(nil, @state_name, success: @success_as_symbol) do
|
13
|
-
transitions to: :closed, from: [:open, :received]
|
14
|
-
end
|
15
|
-
end
|
16
|
-
alias_method :new_event, :event_with_symbol_success_callback
|
17
|
-
|
18
|
-
def event_with_lambda_success_callback
|
19
|
-
@event = Transitions::Event.new(nil, @state_name, success: @success_as_lambda) do
|
20
|
-
transitions to: :closed, from: [:open, :received]
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def event_with_array_success_callback
|
25
|
-
@event = Transitions::Event.new(nil, @state_name, success: @success_as_array) do
|
26
|
-
transitions to: :closed, from: [:open, :received]
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
test 'should set the name' do
|
31
|
-
assert_equal @state_name, new_event.name
|
32
|
-
end
|
33
|
-
|
34
|
-
test 'should set the success callback with a symbol and return a block' do
|
35
|
-
assert_respond_to event_with_symbol_success_callback.success, :call
|
36
|
-
end
|
37
|
-
|
38
|
-
test 'should build a block which calls the given success_callback symbol on the passed record instance' do
|
39
|
-
record = mock('SomeRecordToGetCalled')
|
40
|
-
record.expects(:success_callback)
|
41
|
-
|
42
|
-
event_with_symbol_success_callback.success.call(record)
|
43
|
-
end
|
44
|
-
|
45
|
-
test 'should set the success callback with a lambda' do
|
46
|
-
assert_respond_to event_with_lambda_success_callback.success, :call
|
47
|
-
end
|
48
|
-
|
49
|
-
test 'should build a block which calls the given success_callback lambda on the passed record instance' do
|
50
|
-
record = mock('SomeRecordToGetCalled')
|
51
|
-
record.expects(:success_callback)
|
52
|
-
|
53
|
-
event_with_lambda_success_callback.success.call(record)
|
54
|
-
end
|
55
|
-
|
56
|
-
test 'should set the success callback with an array' do
|
57
|
-
assert_respond_to event_with_array_success_callback.success, :call
|
58
|
-
end
|
59
|
-
|
60
|
-
test 'should build a block which calls the given success_callback array on the passed record instance for each callback' do
|
61
|
-
record = mock('SomeRecordToGetCalled')
|
62
|
-
record.expects(:success_callback).twice
|
63
|
-
|
64
|
-
event_with_array_success_callback.success.call(record)
|
65
|
-
end
|
66
|
-
|
67
|
-
test 'should create StateTransitions' do
|
68
|
-
Transitions::StateTransition.expects(:new).with(to: :closed, from: :open)
|
69
|
-
Transitions::StateTransition.expects(:new).with(to: :closed, from: :received)
|
70
|
-
new_event
|
71
|
-
end
|
72
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
class ArgumentsTestSubject
|
4
|
-
include Transitions
|
5
|
-
attr_accessor :date
|
6
|
-
|
7
|
-
state_machine do
|
8
|
-
state :initial
|
9
|
-
state :opened
|
10
|
-
|
11
|
-
event :open do
|
12
|
-
transitions from: :initial, to: :opened, on_transition: :update_date
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def update_date(date = Date.today)
|
17
|
-
self.date = date
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
class StateMachineMachineTest < Test::Unit::TestCase
|
22
|
-
test 'pass arguments to transition method' do
|
23
|
-
subject = ArgumentsTestSubject.new
|
24
|
-
assert_equal :initial, subject.current_state
|
25
|
-
subject.open!(Date.yesterday)
|
26
|
-
assert_equal :opened, subject.current_state
|
27
|
-
assert_equal Date.yesterday, subject.date
|
28
|
-
end
|
29
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
class TestEventBeingFired < Test::Unit::TestCase
|
4
|
-
test 'should raise an Transitions::InvalidTransition error if the transitions are empty' do
|
5
|
-
event = Transitions::Event.new(nil, :event_that_is_fired)
|
6
|
-
class AnotherDummy; end
|
7
|
-
obj = AnotherDummy.new
|
8
|
-
obj.stubs(:current_state).returns(:running)
|
9
|
-
|
10
|
-
exception = assert_raise Transitions::InvalidTransition do
|
11
|
-
event.fire(obj)
|
12
|
-
end
|
13
|
-
assert_match /Can't fire event `event_that_is_fired` in current state `running` for `TestEventBeingFired::AnotherDummy`/, exception.message
|
14
|
-
end
|
15
|
-
|
16
|
-
test 'should return the state of the first matching transition it finds' do
|
17
|
-
event = Transitions::Event.new(nil, :event) do
|
18
|
-
transitions to: :closed, from: [:open, :received]
|
19
|
-
end
|
20
|
-
|
21
|
-
obj = stub
|
22
|
-
obj.stubs(:current_state).returns(:open)
|
23
|
-
|
24
|
-
assert_equal :closed, event.fire(obj)
|
25
|
-
end
|
26
|
-
end
|
@@ -1,33 +0,0 @@
|
|
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
|
data/test/helper.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require 'active_record'
|
3
|
-
|
4
|
-
require 'transitions'
|
5
|
-
require 'active_model/transitions'
|
6
|
-
|
7
|
-
require 'mocha'
|
8
|
-
require 'random_data'
|
9
|
-
|
10
|
-
def db_defaults!
|
11
|
-
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
|
12
|
-
ActiveRecord::Migration.verbose = false
|
13
|
-
end
|
14
|
-
|
15
|
-
def set_up_db(*migrations)
|
16
|
-
db_defaults!
|
17
|
-
migrations.each { |klass| klass.send :migrate, :up }
|
18
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
class MachineTestSubject
|
2
|
-
include Transitions
|
3
|
-
|
4
|
-
state_machine initial: :open do
|
5
|
-
state :open
|
6
|
-
state :closed
|
7
|
-
|
8
|
-
event :shutdown do
|
9
|
-
transitions from: :open, to: :closed
|
10
|
-
end
|
11
|
-
|
12
|
-
event :timeout do
|
13
|
-
transitions from: :open, to: :closed
|
14
|
-
end
|
15
|
-
|
16
|
-
event :restart do
|
17
|
-
transitions from: :closed, to: :open, guard: :restart_allowed?
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def restart_allowed?(allowed = true)
|
22
|
-
allowed
|
23
|
-
end
|
24
|
-
|
25
|
-
def event_failed(*)
|
26
|
-
end
|
27
|
-
end
|