transitions 0.0.13 → 0.0.14
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.
- data/CHANGELOG.md +3 -0
- data/Gemfile.lock +1 -1
- data/README.rdoc +5 -5
- data/lib/active_model/transitions.rb +74 -0
- data/lib/active_record/transitions.rb +3 -72
- data/lib/transitions/event.rb +5 -1
- data/lib/transitions/version.rb +1 -1
- data/test/helper.rb +1 -1
- data/test/test_active_record.rb +3 -3
- data/test/test_active_record_timestamps.rb +2 -2
- data/test/test_event_being_fired.rb +6 -2
- metadata +17 -15
data/CHANGELOG.md
ADDED
data/Gemfile.lock
CHANGED
data/README.rdoc
CHANGED
@@ -12,11 +12,11 @@
|
|
12
12
|
|
13
13
|
This goes into your Gemfile:
|
14
14
|
|
15
|
-
gem "transitions", :require => ["transitions", "
|
15
|
+
gem "transitions", :require => ["transitions", "active_model/transitions"]
|
16
16
|
|
17
|
-
… and this into your
|
17
|
+
… and this into your ORM model:
|
18
18
|
|
19
|
-
include
|
19
|
+
include ActiveModel::Transitions
|
20
20
|
|
21
21
|
== Standalone
|
22
22
|
|
@@ -62,7 +62,7 @@ bang(!)-version will call <tt>write_state</tt>.
|
|
62
62
|
Given a model like this:
|
63
63
|
|
64
64
|
class Order < ActiveRecord::Base
|
65
|
-
include
|
65
|
+
include ActiveModel::Transitions
|
66
66
|
state_machine :auto_scopes => true do
|
67
67
|
state :pick_line_items
|
68
68
|
state :picking_line_items
|
@@ -117,7 +117,7 @@ the name of the timestamp column.
|
|
117
117
|
|
118
118
|
# This will look for an attribute named repaired_on to update upon save
|
119
119
|
event :rebuild, :timestamp => :repaired_on do
|
120
|
-
|
120
|
+
transitions :from => :exploded, :to => :rebuilt
|
121
121
|
end
|
122
122
|
|
123
123
|
== Listing all the available states
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# Copyright (c) 2009 Rick Olson
|
2
|
+
|
3
|
+
# Permission is hereby granted, free of charge, to any person
|
4
|
+
# obtaining a copy of this software and associated documentation files
|
5
|
+
# (the "Software"), to deal in the Software without restriction,
|
6
|
+
# including without limitation the rights to use, copy, modify, merge,
|
7
|
+
# publish, distribute, sublicense, and/or sell copies of the Software,
|
8
|
+
# and to permit persons to whom the Software is furnished to do so,
|
9
|
+
# subject to the following conditions:
|
10
|
+
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
18
|
+
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
19
|
+
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
module ActiveModel
|
24
|
+
module Transitions
|
25
|
+
extend ActiveSupport::Concern
|
26
|
+
|
27
|
+
included do
|
28
|
+
include ::Transitions
|
29
|
+
after_initialize :set_initial_state
|
30
|
+
validates_presence_of :state
|
31
|
+
validate :state_inclusion
|
32
|
+
end
|
33
|
+
|
34
|
+
# The optional options argument is passed to find when reloading so you may
|
35
|
+
# do e.g. record.reload(:lock => true) to reload the same record with an
|
36
|
+
# exclusive row lock.
|
37
|
+
def reload(options = nil)
|
38
|
+
super.tap do
|
39
|
+
self.class.state_machines.values.each do |sm|
|
40
|
+
remove_instance_variable(sm.current_state_variable) if instance_variable_defined?(sm.current_state_variable)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
|
47
|
+
def write_state(state_machine, state)
|
48
|
+
ivar = state_machine.current_state_variable
|
49
|
+
prev_state = current_state(state_machine.name)
|
50
|
+
instance_variable_set(ivar, state)
|
51
|
+
self.state = state.to_s
|
52
|
+
save!
|
53
|
+
rescue ActiveRecord::RecordInvalid
|
54
|
+
self.state = prev_state.to_s
|
55
|
+
instance_variable_set(ivar, prev_state)
|
56
|
+
raise
|
57
|
+
end
|
58
|
+
|
59
|
+
def read_state(state_machine)
|
60
|
+
self.state && self.state.to_sym
|
61
|
+
end
|
62
|
+
|
63
|
+
def set_initial_state
|
64
|
+
self.state ||= self.class.state_machine.initial_state.to_s if self.has_attribute?(:state)
|
65
|
+
end
|
66
|
+
|
67
|
+
def state_inclusion
|
68
|
+
unless self.class.state_machine.states.map{|s| s.name.to_s }.include?(self.state.to_s)
|
69
|
+
self.errors.add(:state, :inclusion, :value => self.state)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
@@ -1,74 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
# Permission is hereby granted, free of charge, to any person
|
4
|
-
# obtaining a copy of this software and associated documentation files
|
5
|
-
# (the "Software"), to deal in the Software without restriction,
|
6
|
-
# including without limitation the rights to use, copy, modify, merge,
|
7
|
-
# publish, distribute, sublicense, and/or sell copies of the Software,
|
8
|
-
# and to permit persons to whom the Software is furnished to do so,
|
9
|
-
# subject to the following conditions:
|
10
|
-
|
11
|
-
# The above copyright notice and this permission notice shall be
|
12
|
-
# included in all copies or substantial portions of the Software.
|
13
|
-
|
14
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
-
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
-
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
-
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
18
|
-
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
19
|
-
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
-
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
-
# SOFTWARE.
|
1
|
+
require_relative '../active_model/transitions'
|
22
2
|
|
23
3
|
module ActiveRecord
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
included do
|
28
|
-
include ::Transitions
|
29
|
-
after_initialize :set_initial_state
|
30
|
-
validates_presence_of :state
|
31
|
-
validate :state_inclusion
|
32
|
-
end
|
33
|
-
|
34
|
-
# The optional options argument is passed to find when reloading so you may
|
35
|
-
# do e.g. record.reload(:lock => true) to reload the same record with an
|
36
|
-
# exclusive row lock.
|
37
|
-
def reload(options = nil)
|
38
|
-
super.tap do
|
39
|
-
self.class.state_machines.values.each do |sm|
|
40
|
-
remove_instance_variable(sm.current_state_variable) if instance_variable_defined?(sm.current_state_variable)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
protected
|
46
|
-
|
47
|
-
def write_state(state_machine, state)
|
48
|
-
ivar = state_machine.current_state_variable
|
49
|
-
prev_state = current_state(state_machine.name)
|
50
|
-
instance_variable_set(ivar, state)
|
51
|
-
self.state = state.to_s
|
52
|
-
save!
|
53
|
-
rescue ActiveRecord::RecordInvalid
|
54
|
-
self.state = prev_state.to_s
|
55
|
-
instance_variable_set(ivar, prev_state)
|
56
|
-
raise
|
57
|
-
end
|
58
|
-
|
59
|
-
def read_state(state_machine)
|
60
|
-
self.state && self.state.to_sym
|
61
|
-
end
|
62
|
-
|
63
|
-
def set_initial_state
|
64
|
-
self.state ||= self.class.state_machine.initial_state.to_s if self.has_attribute?(:state)
|
65
|
-
end
|
66
|
-
|
67
|
-
def state_inclusion
|
68
|
-
unless self.class.state_machine.states.map{|s| s.name.to_s }.include?(self.state.to_s)
|
69
|
-
self.errors.add(:state, :inclusion, :value => self.state)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
4
|
+
Transitions = ActiveModel::Transitions
|
5
|
+
end
|
data/lib/transitions/event.rb
CHANGED
@@ -40,7 +40,7 @@ module Transitions
|
|
40
40
|
|
41
41
|
def fire(obj, to_state = nil, *args)
|
42
42
|
transitions = @transitions.select { |t| t.from == obj.current_state(@machine ? @machine.name : nil) }
|
43
|
-
raise InvalidTransition if transitions.size == 0
|
43
|
+
raise InvalidTransition, error_message_for_invalid_transitions(obj) if transitions.size == 0
|
44
44
|
|
45
45
|
next_state = nil
|
46
46
|
transitions.each do |transition|
|
@@ -133,5 +133,9 @@ module Transitions
|
|
133
133
|
lambda { |record| record.send(callback_symbol_or_proc) }
|
134
134
|
end
|
135
135
|
end
|
136
|
+
|
137
|
+
def error_message_for_invalid_transitions(obj)
|
138
|
+
"No transitions present for `#{obj.class.name}` #{obj.class < ActiveRecord::Base && obj.persisted? ? "with ID #{obj.id} " : nil}with current state `#{obj.current_state}`"
|
139
|
+
end
|
136
140
|
end
|
137
141
|
end
|
data/lib/transitions/version.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -9,7 +9,7 @@ require "ruby-debug"
|
|
9
9
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
|
10
10
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
11
11
|
require "transitions"
|
12
|
-
require "
|
12
|
+
require "active_model/transitions"
|
13
13
|
|
14
14
|
class Test::Unit::TestCase
|
15
15
|
|
data/test/test_active_record.rb
CHANGED
@@ -33,7 +33,7 @@ CreateLightBulbs.migrate(:up)
|
|
33
33
|
CreateLights.migrate(:up)
|
34
34
|
|
35
35
|
class TrafficLight < ActiveRecord::Base
|
36
|
-
include
|
36
|
+
include ActiveModel::Transitions
|
37
37
|
|
38
38
|
state_machine :auto_scopes => true do
|
39
39
|
state :off
|
@@ -73,7 +73,7 @@ class ConditionalValidatingTrafficLight < TrafficLight
|
|
73
73
|
end
|
74
74
|
|
75
75
|
class LightBulb < ActiveRecord::Base
|
76
|
-
include
|
76
|
+
include ActiveModel::Transitions
|
77
77
|
|
78
78
|
state_machine do
|
79
79
|
state :off
|
@@ -203,7 +203,7 @@ class TestScopes < Test::Unit::TestCase
|
|
203
203
|
test 'scope generation raises an exception if we try to overwrite an existing method' do
|
204
204
|
assert_raise(Transitions::InvalidMethodOverride) {
|
205
205
|
class Light < ActiveRecord::Base
|
206
|
-
include
|
206
|
+
include ActiveModel::Transitions
|
207
207
|
|
208
208
|
state_machine :auto_scopes => true do
|
209
209
|
state :new
|
@@ -4,7 +4,7 @@ require 'active_support/core_ext/module/aliasing'
|
|
4
4
|
create_database
|
5
5
|
|
6
6
|
class Order < ActiveRecord::Base
|
7
|
-
include
|
7
|
+
include ActiveModel::Transitions
|
8
8
|
|
9
9
|
state_machine do
|
10
10
|
state :opened
|
@@ -104,7 +104,7 @@ class TestActiveRecordTimestamps < Test::Unit::TestCase
|
|
104
104
|
test "passing an invalid value to timestamp options should raise an exception" do
|
105
105
|
assert_raise(ArgumentError) do
|
106
106
|
class Order < ActiveRecord::Base
|
107
|
-
include
|
107
|
+
include ActiveModel::Transitions
|
108
108
|
state_machine do
|
109
109
|
event :replace, timestamp: 1 do
|
110
110
|
transitions :from => :prepared, :to => :placed
|
@@ -3,10 +3,14 @@ require "helper"
|
|
3
3
|
class TestEventBeingFired < Test::Unit::TestCase
|
4
4
|
test "should raise an Transitions::InvalidTransition error if the transitions are empty" do
|
5
5
|
event = Transitions::Event.new(nil, :event)
|
6
|
+
class AnotherDummy; end
|
7
|
+
obj = AnotherDummy.new
|
8
|
+
obj.stubs(:current_state).returns(:running)
|
6
9
|
|
7
|
-
assert_raise Transitions::InvalidTransition do
|
8
|
-
event.fire(
|
10
|
+
exception = assert_raise Transitions::InvalidTransition do
|
11
|
+
event.fire(obj)
|
9
12
|
end
|
13
|
+
assert_match /No transitions present for `TestEventBeingFired::AnotherDummy` with current state `running`/, exception.message
|
10
14
|
end
|
11
15
|
|
12
16
|
test "should return the state of the first matching transition it finds" do
|
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.14
|
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:
|
13
|
+
date: 2012-04-16 00:00:00.000000000Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
17
|
-
requirement: &
|
17
|
+
requirement: &74398430 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ~>
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: '1'
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *74398430
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: test-unit
|
28
|
-
requirement: &
|
28
|
+
requirement: &74398010 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ~>
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: '2.2'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *74398010
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: mocha
|
39
|
-
requirement: &
|
39
|
+
requirement: &74397730 !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: *74397730
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: sqlite3-ruby
|
50
|
-
requirement: &
|
50
|
+
requirement: &74397410 !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: *74397410
|
59
59
|
- !ruby/object:Gem::Dependency
|
60
60
|
name: activerecord
|
61
|
-
requirement: &
|
61
|
+
requirement: &74396940 !ruby/object:Gem::Requirement
|
62
62
|
none: false
|
63
63
|
requirements:
|
64
64
|
- - ~>
|
@@ -66,10 +66,10 @@ dependencies:
|
|
66
66
|
version: '3'
|
67
67
|
type: :development
|
68
68
|
prerelease: false
|
69
|
-
version_requirements: *
|
69
|
+
version_requirements: *74396940
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: ruby-debug19
|
72
|
-
requirement: &
|
72
|
+
requirement: &74396440 !ruby/object:Gem::Requirement
|
73
73
|
none: false
|
74
74
|
requirements:
|
75
75
|
- - ! '>='
|
@@ -77,7 +77,7 @@ dependencies:
|
|
77
77
|
version: '0'
|
78
78
|
type: :development
|
79
79
|
prerelease: false
|
80
|
-
version_requirements: *
|
80
|
+
version_requirements: *74396440
|
81
81
|
description: Lightweight state machine extracted from ActiveModel
|
82
82
|
email: timo.roessner@googlemail.com
|
83
83
|
executables: []
|
@@ -87,11 +87,13 @@ files:
|
|
87
87
|
- .gitignore
|
88
88
|
- .rvmrc
|
89
89
|
- .travis.yml
|
90
|
+
- CHANGELOG.md
|
90
91
|
- Gemfile
|
91
92
|
- Gemfile.lock
|
92
93
|
- LICENSE
|
93
94
|
- README.rdoc
|
94
95
|
- Rakefile
|
96
|
+
- lib/active_model/transitions.rb
|
95
97
|
- lib/active_record/transitions.rb
|
96
98
|
- lib/transitions.rb
|
97
99
|
- lib/transitions/event.rb
|
@@ -128,7 +130,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
128
130
|
version: '0'
|
129
131
|
segments:
|
130
132
|
- 0
|
131
|
-
hash:
|
133
|
+
hash: 950488929
|
132
134
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
135
|
none: false
|
134
136
|
requirements:
|