transitions 1.0.0 → 1.0.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.
- 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
|