transitions 0.0.17 → 0.0.18
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +5 -0
- data/lib/transitions/state.rb +26 -1
- data/lib/transitions/version.rb +1 -1
- data/lib/transitions.rb +3 -7
- data/test/db/create_db.rb +3 -0
- data/test/helper.rb +1 -0
- data/test/test_active_record.rb +29 -12
- data/test/test_state.rb +49 -20
- data/transitions.gemspec +1 -0
- metadata +26 -15
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
# 0.0.18 (2012-05-18)
|
2
|
+
|
3
|
+
* (troessner) Remove `define_state_query_method` from public API
|
4
|
+
* (troessner) Do not override existing methods when defining state query methods but warn the user.
|
5
|
+
|
1
6
|
# 0.0.17 (2012-05-02):
|
2
7
|
|
3
8
|
* (zmillman) Add write_state_without_persistence.
|
data/lib/transitions/state.rb
CHANGED
@@ -27,7 +27,7 @@ module Transitions
|
|
27
27
|
def initialize(name, options = {})
|
28
28
|
@name = name
|
29
29
|
if machine = options.delete(:machine)
|
30
|
-
|
30
|
+
define_state_query_method(machine)
|
31
31
|
end
|
32
32
|
update(options)
|
33
33
|
end
|
@@ -63,5 +63,30 @@ module Transitions
|
|
63
63
|
@options = options
|
64
64
|
self
|
65
65
|
end
|
66
|
+
|
67
|
+
private
|
68
|
+
def define_state_query_method(machine)
|
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
|
89
|
+
end
|
90
|
+
end
|
66
91
|
end
|
67
92
|
end
|
data/lib/transitions/version.rb
CHANGED
data/lib/transitions.rb
CHANGED
@@ -32,7 +32,7 @@ module Transitions
|
|
32
32
|
|
33
33
|
module ClassMethods
|
34
34
|
def inherited(klass)
|
35
|
-
super
|
35
|
+
super # Make sure we call other callbacks possibly defined upstream the ancestor chain.
|
36
36
|
klass.state_machines = state_machines
|
37
37
|
end
|
38
38
|
|
@@ -40,6 +40,7 @@ module Transitions
|
|
40
40
|
@state_machines ||= {}
|
41
41
|
end
|
42
42
|
|
43
|
+
# The only reason we need this method is for the inherited callback.
|
43
44
|
def state_machines=(value)
|
44
45
|
@state_machines = value ? value.dup : nil
|
45
46
|
end
|
@@ -57,18 +58,13 @@ module Transitions
|
|
57
58
|
def available_states(name = :default)
|
58
59
|
state_machines[name].states.map(&:name).sort_by {|x| x.to_s}
|
59
60
|
end
|
60
|
-
|
61
|
-
def define_state_query_method(state_name)
|
62
|
-
name = "#{state_name}?"
|
63
|
-
undef_method(name) if method_defined?(name)
|
64
|
-
define_method(name) { current_state.to_s == %(#{state_name}) }
|
65
|
-
end
|
66
61
|
end
|
67
62
|
|
68
63
|
def self.included(base)
|
69
64
|
base.extend(ClassMethods)
|
70
65
|
end
|
71
66
|
|
67
|
+
# TODO Do we need this method really? Also, it's not a beauty, refactor at least.
|
72
68
|
def current_state(name = nil, new_state = nil, persist = false)
|
73
69
|
sm = self.class.state_machine(name)
|
74
70
|
ivar = sm.current_state_variable
|
data/test/db/create_db.rb
CHANGED
data/test/helper.rb
CHANGED
data/test/test_active_record.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require "helper"
|
2
2
|
require 'active_support/core_ext/module/aliasing'
|
3
3
|
|
4
|
+
# TODO Tests here are quite messy, clean up.
|
5
|
+
|
4
6
|
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
5
7
|
|
6
8
|
class CreateTrafficLights < ActiveRecord::Migration
|
@@ -188,34 +190,49 @@ class TestNewActiveRecord < TestActiveRecord
|
|
188
190
|
|
189
191
|
end
|
190
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
|
+
|
191
211
|
class TestScopes < Test::Unit::TestCase
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
assert_equal TrafficLight.off.first, @light
|
196
|
-
assert TrafficLight.red.empty?
|
212
|
+
def setup
|
213
|
+
create_database
|
214
|
+
@bunny = Bunny.create!
|
197
215
|
end
|
198
216
|
|
199
217
|
test "scopes exist" do
|
200
|
-
assert_respond_to
|
201
|
-
|
202
|
-
|
203
|
-
|
218
|
+
assert_respond_to Bunny, :hobbling
|
219
|
+
end
|
220
|
+
|
221
|
+
test "scope returns correct object" do
|
222
|
+
assert_equal Bunny.hobbling.first, @bunny
|
204
223
|
end
|
205
224
|
|
206
225
|
test 'scopes are only generated if we explicitly say so' do
|
207
226
|
assert_not_respond_to LightBulb, :off
|
208
|
-
assert_not_respond_to LightBulb, :on
|
209
227
|
end
|
210
228
|
|
211
229
|
test 'scope generation raises an exception if we try to overwrite an existing method' do
|
212
230
|
assert_raise(Transitions::InvalidMethodOverride) {
|
213
|
-
class
|
231
|
+
class TrafficLight < ActiveRecord::Base
|
214
232
|
include ActiveModel::Transitions
|
215
233
|
|
216
234
|
state_machine :auto_scopes => true do
|
217
235
|
state :new
|
218
|
-
state :broken
|
219
236
|
end
|
220
237
|
end
|
221
238
|
}
|
data/test/test_state.rb
CHANGED
@@ -1,50 +1,50 @@
|
|
1
1
|
require "helper"
|
2
2
|
|
3
|
-
class StateTestSubject
|
4
|
-
include Transitions
|
5
|
-
|
6
|
-
state_machine do
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
3
|
class TestState < Test::Unit::TestCase
|
11
4
|
def setup
|
5
|
+
@state_test_subject = Class.new do
|
6
|
+
include Transitions
|
7
|
+
state_machine do
|
8
|
+
end
|
9
|
+
end
|
12
10
|
@state_name = :astate
|
13
|
-
@machine =
|
14
|
-
@options = { :
|
11
|
+
@machine = @state_test_subject.state_machine
|
12
|
+
@options = { :machine => @machine, :custom_key => :my_key }
|
13
|
+
@state = Transitions::State.new(@state_name, @options)
|
15
14
|
end
|
16
15
|
|
17
|
-
def
|
18
|
-
|
16
|
+
def new_state_name
|
17
|
+
Random.alphanumeric(16)
|
19
18
|
end
|
20
19
|
|
21
20
|
test "sets the name" do
|
22
|
-
assert_equal :astate,
|
21
|
+
assert_equal :astate, @state.name
|
23
22
|
end
|
24
23
|
|
25
24
|
test "sets the display_name from name" do
|
26
|
-
assert_equal "Astate",
|
25
|
+
assert_equal "Astate", @state.display_name
|
27
26
|
end
|
28
27
|
|
29
28
|
test "sets the display_name from options" do
|
30
|
-
assert_equal "A State",
|
29
|
+
assert_equal "A State", Transitions::State.new(new_state_name, @options.merge(:display => "A State")).display_name
|
31
30
|
end
|
32
31
|
|
33
32
|
test "sets the options and expose them as options" do
|
34
33
|
@options.delete(:machine)
|
35
|
-
|
34
|
+
state = Transitions::State.new new_state_name, @options
|
35
|
+
assert_equal @options, state.options
|
36
36
|
end
|
37
37
|
|
38
38
|
test "equals a symbol of the same name" do
|
39
|
-
assert_equal
|
39
|
+
assert_equal @state, :astate
|
40
40
|
end
|
41
41
|
|
42
42
|
test "equals a State of the same name" do
|
43
|
-
assert_equal
|
43
|
+
assert_equal @state, @state
|
44
44
|
end
|
45
45
|
|
46
46
|
test "should send a message to the record for an action if the action is present as a symbol" do
|
47
|
-
state =
|
47
|
+
state = Transitions::State.new new_state_name, @options.merge(:entering => :foo)
|
48
48
|
|
49
49
|
record = stub
|
50
50
|
record.expects(:foo)
|
@@ -53,7 +53,7 @@ class TestState < Test::Unit::TestCase
|
|
53
53
|
end
|
54
54
|
|
55
55
|
test "should send a message to the record for an action if the action is present as a string" do
|
56
|
-
state =
|
56
|
+
state = Transitions::State.new new_state_name, @options.merge(:entering => "foo")
|
57
57
|
|
58
58
|
record = stub
|
59
59
|
record.expects(:foo)
|
@@ -62,7 +62,7 @@ class TestState < Test::Unit::TestCase
|
|
62
62
|
end
|
63
63
|
|
64
64
|
test "should call a proc, passing in the record for an action if the action is present" do
|
65
|
-
state =
|
65
|
+
state = Transitions::State.new new_state_name, @options.merge(:entering => Proc.new {|r| r.foobar})
|
66
66
|
|
67
67
|
record = stub
|
68
68
|
record.expects(:foobar)
|
@@ -70,3 +70,32 @@ class TestState < Test::Unit::TestCase
|
|
70
70
|
state.call_action(:entering, record)
|
71
71
|
end
|
72
72
|
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
|
data/transitions.gemspec
CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.add_development_dependency "test-unit", "~> 2.2"
|
19
19
|
s.add_development_dependency "mocha"
|
20
20
|
s.add_development_dependency "rake"
|
21
|
+
s.add_development_dependency "random_data"
|
21
22
|
s.add_development_dependency "sqlite3"
|
22
23
|
s.add_development_dependency "activerecord", "~> 3"
|
23
24
|
|
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.18
|
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: 2012-05-
|
13
|
+
date: 2012-05-18 00:00:00.000000000Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
17
|
-
requirement: &
|
17
|
+
requirement: &76418870 !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: *76418870
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: test-unit
|
28
|
-
requirement: &
|
28
|
+
requirement: &76418470 !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: *76418470
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: mocha
|
39
|
-
requirement: &
|
39
|
+
requirement: &76418120 !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: *76418120
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: rake
|
50
|
-
requirement: &
|
50
|
+
requirement: &76417650 !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
52
52
|
requirements:
|
53
53
|
- - ! '>='
|
@@ -55,10 +55,21 @@ dependencies:
|
|
55
55
|
version: '0'
|
56
56
|
type: :development
|
57
57
|
prerelease: false
|
58
|
-
version_requirements: *
|
58
|
+
version_requirements: *76417650
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: random_data
|
61
|
+
requirement: &76417170 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *76417170
|
59
70
|
- !ruby/object:Gem::Dependency
|
60
71
|
name: sqlite3
|
61
|
-
requirement: &
|
72
|
+
requirement: &76416820 !ruby/object:Gem::Requirement
|
62
73
|
none: false
|
63
74
|
requirements:
|
64
75
|
- - ! '>='
|
@@ -66,10 +77,10 @@ dependencies:
|
|
66
77
|
version: '0'
|
67
78
|
type: :development
|
68
79
|
prerelease: false
|
69
|
-
version_requirements: *
|
80
|
+
version_requirements: *76416820
|
70
81
|
- !ruby/object:Gem::Dependency
|
71
82
|
name: activerecord
|
72
|
-
requirement: &
|
83
|
+
requirement: &76416030 !ruby/object:Gem::Requirement
|
73
84
|
none: false
|
74
85
|
requirements:
|
75
86
|
- - ~>
|
@@ -77,7 +88,7 @@ dependencies:
|
|
77
88
|
version: '3'
|
78
89
|
type: :development
|
79
90
|
prerelease: false
|
80
|
-
version_requirements: *
|
91
|
+
version_requirements: *76416030
|
81
92
|
description: Lightweight state machine extracted from ActiveModel
|
82
93
|
email: timo.roessner@googlemail.com
|
83
94
|
executables: []
|
@@ -129,7 +140,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
129
140
|
version: '0'
|
130
141
|
segments:
|
131
142
|
- 0
|
132
|
-
hash: -
|
143
|
+
hash: -1015670387
|
133
144
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
145
|
none: false
|
135
146
|
requirements:
|