Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
db49c706
R
rails
项目概览
张重言
/
rails
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rails
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
db49c706
编写于
1月 30, 2010
作者:
J
Joshua Peek
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Axe AM state machine
We're going do it eventually, get it done before 3.0 is final.
上级
657d8558
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
0 addition
and
949 deletion
+0
-949
activemodel/lib/active_model.rb
activemodel/lib/active_model.rb
+0
-1
activemodel/lib/active_model/state_machine.rb
activemodel/lib/active_model/state_machine.rb
+0
-70
activemodel/lib/active_model/state_machine/event.rb
activemodel/lib/active_model/state_machine/event.rb
+0
-62
activemodel/lib/active_model/state_machine/machine.rb
activemodel/lib/active_model/state_machine/machine.rb
+0
-75
activemodel/lib/active_model/state_machine/state.rb
activemodel/lib/active_model/state_machine/state.rb
+0
-47
activemodel/lib/active_model/state_machine/state_transition.rb
...emodel/lib/active_model/state_machine/state_transition.rb
+0
-40
activemodel/test/cases/state_machine/event_test.rb
activemodel/test/cases/state_machine/event_test.rb
+0
-49
activemodel/test/cases/state_machine/machine_test.rb
activemodel/test/cases/state_machine/machine_test.rb
+0
-43
activemodel/test/cases/state_machine/state_test.rb
activemodel/test/cases/state_machine/state_test.rb
+0
-72
activemodel/test/cases/state_machine/state_transition_test.rb
...vemodel/test/cases/state_machine/state_transition_test.rb
+0
-84
activemodel/test/cases/state_machine_test.rb
activemodel/test/cases/state_machine_test.rb
+0
-312
activerecord/lib/active_record.rb
activerecord/lib/active_record.rb
+0
-1
activerecord/lib/active_record/state_machine.rb
activerecord/lib/active_record/state_machine.rb
+0
-24
activerecord/test/cases/state_machine_test.rb
activerecord/test/cases/state_machine_test.rb
+0
-42
activerecord/test/models/traffic_light.rb
activerecord/test/models/traffic_light.rb
+0
-27
未找到文件。
activemodel/lib/active_model.rb
浏览文件 @
db49c706
...
...
@@ -43,7 +43,6 @@ module ActiveModel
autoload
:Observer
,
'active_model/observing'
autoload
:Observing
autoload
:Serialization
autoload
:StateMachine
autoload
:TestCase
autoload
:Translation
autoload
:VERSION
...
...
activemodel/lib/active_model/state_machine.rb
已删除
100644 → 0
浏览文件 @
657d8558
module
ActiveModel
module
StateMachine
autoload
:Event
,
'active_model/state_machine/event'
autoload
:Machine
,
'active_model/state_machine/machine'
autoload
:State
,
'active_model/state_machine/state'
autoload
:StateTransition
,
'active_model/state_machine/state_transition'
extend
ActiveSupport
::
Concern
class
InvalidTransition
<
Exception
end
module
ClassMethods
def
inherited
(
klass
)
super
klass
.
state_machines
=
state_machines
end
def
state_machines
@state_machines
||=
{}
end
def
state_machines
=
(
value
)
@state_machines
=
value
?
value
.
dup
:
nil
end
def
state_machine
(
name
=
nil
,
options
=
{},
&
block
)
if
name
.
is_a?
(
Hash
)
options
=
name
name
=
nil
end
name
||=
:default
state_machines
[
name
]
||=
Machine
.
new
(
self
,
name
)
block
?
state_machines
[
name
].
update
(
options
,
&
block
)
:
state_machines
[
name
]
end
def
define_state_query_method
(
state_name
)
name
=
"
#{
state_name
}
?"
undef_method
(
name
)
if
method_defined?
(
name
)
class_eval
"def
#{
name
}
; current_state.to_s == %(
#{
state_name
}
) end"
end
end
def
current_state
(
name
=
nil
,
new_state
=
nil
,
persist
=
false
)
sm
=
self
.
class
.
state_machine
(
name
)
ivar
=
sm
.
current_state_variable
if
name
&&
new_state
if
persist
&&
respond_to?
(
:write_state
)
write_state
(
sm
,
new_state
)
end
if
respond_to?
(
:write_state_without_persistence
)
write_state_without_persistence
(
sm
,
new_state
)
end
instance_variable_set
(
ivar
,
new_state
)
else
instance_variable_set
(
ivar
,
nil
)
unless
instance_variable_defined?
(
ivar
)
value
=
instance_variable_get
(
ivar
)
return
value
if
value
if
respond_to?
(
:read_state
)
value
=
instance_variable_set
(
ivar
,
read_state
(
sm
))
end
value
||
sm
.
initial_state
end
end
end
end
activemodel/lib/active_model/state_machine/event.rb
已删除
100644 → 0
浏览文件 @
657d8558
module
ActiveModel
module
StateMachine
class
Event
attr_reader
:name
,
:success
def
initialize
(
machine
,
name
,
options
=
{},
&
block
)
@machine
,
@name
,
@transitions
=
machine
,
name
,
[]
if
machine
machine
.
klass
.
send
(
:define_method
,
"
#{
name
}
!"
)
do
|*
args
|
machine
.
fire_event
(
name
,
self
,
true
,
*
args
)
end
machine
.
klass
.
send
(
:define_method
,
name
.
to_s
)
do
|*
args
|
machine
.
fire_event
(
name
,
self
,
false
,
*
args
)
end
end
update
(
options
,
&
block
)
end
def
fire
(
obj
,
to_state
=
nil
,
*
args
)
transitions
=
@transitions
.
select
{
|
t
|
t
.
from
==
obj
.
current_state
(
@machine
?
@machine
.
name
:
nil
)
}
raise
InvalidTransition
if
transitions
.
size
==
0
next_state
=
nil
transitions
.
each
do
|
transition
|
next
if
to_state
&&
!
Array
(
transition
.
to
).
include?
(
to_state
)
if
transition
.
perform
(
obj
)
next_state
=
to_state
||
Array
(
transition
.
to
).
first
transition
.
execute
(
obj
,
*
args
)
break
end
end
next_state
end
def
transitions_from_state?
(
state
)
@transitions
.
any?
{
|
t
|
t
.
from?
state
}
end
def
==
(
event
)
if
event
.
is_a?
Symbol
name
==
event
else
name
==
event
.
name
end
end
def
update
(
options
=
{},
&
block
)
if
options
.
key?
(
:success
)
then
@success
=
options
[
:success
]
end
if
block
then
instance_eval
(
&
block
)
end
self
end
private
def
transitions
(
trans_opts
)
Array
(
trans_opts
[
:from
]).
each
do
|
s
|
@transitions
<<
StateTransition
.
new
(
trans_opts
.
merge
({
:from
=>
s
.
to_sym
}))
end
end
end
end
end
activemodel/lib/active_model/state_machine/machine.rb
已删除
100644 → 0
浏览文件 @
657d8558
module
ActiveModel
module
StateMachine
class
Machine
attr_writer
:initial_state
attr_accessor
:states
,
:events
,
:state_index
attr_reader
:klass
,
:name
def
initialize
(
klass
,
name
,
options
=
{},
&
block
)
@klass
,
@name
,
@states
,
@state_index
,
@events
=
klass
,
name
,
[],
{},
{}
update
(
options
,
&
block
)
end
def
initial_state
@initial_state
||=
(
states
.
first
?
states
.
first
.
name
:
nil
)
end
def
update
(
options
=
{},
&
block
)
if
options
.
key?
(
:initial
)
then
@initial_state
=
options
[
:initial
]
end
if
block
then
instance_eval
(
&
block
)
end
self
end
def
fire_event
(
event
,
record
,
persist
,
*
args
)
state_index
[
record
.
current_state
(
@name
)].
call_action
(
:exit
,
record
)
if
new_state
=
@events
[
event
].
fire
(
record
,
*
args
)
state_index
[
new_state
].
call_action
(
:enter
,
record
)
if
record
.
respond_to?
(
event_fired_callback
)
record
.
send
(
event_fired_callback
,
record
.
current_state
,
new_state
)
end
record
.
current_state
(
@name
,
new_state
,
persist
)
record
.
send
(
@events
[
event
].
success
)
if
@events
[
event
].
success
true
else
if
record
.
respond_to?
(
event_failed_callback
)
record
.
send
(
event_failed_callback
,
event
)
end
false
end
end
def
states_for_select
states
.
map
{
|
st
|
[
st
.
display_name
,
st
.
name
.
to_s
]
}
end
def
events_for
(
state
)
events
=
@events
.
values
.
select
{
|
event
|
event
.
transitions_from_state?
(
state
)
}
events
.
map!
{
|
event
|
event
.
name
}
end
def
current_state_variable
"@
#{
@name
}
_current_state"
end
private
def
state
(
name
,
options
=
{})
@states
<<
(
state_index
[
name
]
||=
State
.
new
(
name
,
:machine
=>
self
)).
update
(
options
)
end
def
event
(
name
,
options
=
{},
&
block
)
(
@events
[
name
]
||=
Event
.
new
(
self
,
name
)).
update
(
options
,
&
block
)
end
def
event_fired_callback
@event_fired_callback
||=
(
@name
==
:default
?
''
:
"
#{
@name
}
_"
)
+
'event_fired'
end
def
event_failed_callback
@event_failed_callback
||=
(
@name
==
:default
?
''
:
"
#{
@name
}
_"
)
+
'event_failed'
end
end
end
end
activemodel/lib/active_model/state_machine/state.rb
已删除
100644 → 0
浏览文件 @
657d8558
module
ActiveModel
module
StateMachine
class
State
attr_reader
:name
,
:options
def
initialize
(
name
,
options
=
{})
@name
=
name
if
machine
=
options
.
delete
(
:machine
)
machine
.
klass
.
define_state_query_method
(
name
)
end
update
(
options
)
end
def
==
(
state
)
if
state
.
is_a?
Symbol
name
==
state
else
name
==
state
.
name
end
end
def
call_action
(
action
,
record
)
action
=
@options
[
action
]
case
action
when
Symbol
,
String
record
.
send
(
action
)
when
Proc
action
.
call
(
record
)
end
end
def
display_name
@display_name
||=
name
.
to_s
.
gsub
(
/_/
,
' '
).
capitalize
end
def
for_select
[
display_name
,
name
.
to_s
]
end
def
update
(
options
=
{})
if
options
.
key?
(
:display
)
then
@display_name
=
options
.
delete
(
:display
)
end
@options
=
options
self
end
end
end
end
activemodel/lib/active_model/state_machine/state_transition.rb
已删除
100644 → 0
浏览文件 @
657d8558
module
ActiveModel
module
StateMachine
class
StateTransition
attr_reader
:from
,
:to
,
:options
def
initialize
(
opts
)
@from
,
@to
,
@guard
,
@on_transition
=
opts
[
:from
],
opts
[
:to
],
opts
[
:guard
],
opts
[
:on_transition
]
@options
=
opts
end
def
perform
(
obj
)
case
@guard
when
Symbol
,
String
obj
.
send
(
@guard
)
when
Proc
@guard
.
call
(
obj
)
else
true
end
end
def
execute
(
obj
,
*
args
)
case
@on_transition
when
Symbol
,
String
obj
.
send
(
@on_transition
,
*
args
)
when
Proc
@on_transition
.
call
(
obj
,
*
args
)
end
end
def
==
(
obj
)
@from
==
obj
.
from
&&
@to
==
obj
.
to
end
def
from?
(
value
)
@from
==
value
end
end
end
end
activemodel/test/cases/state_machine/event_test.rb
已删除
100644 → 0
浏览文件 @
657d8558
require
'cases/helper'
class
EventTest
<
ActiveModel
::
TestCase
def
setup
@state_name
=
:close_order
@success
=
:success_callback
end
def
new_event
@event
=
ActiveModel
::
StateMachine
::
Event
.
new
(
nil
,
@state_name
,
{
:success
=>
@success
})
do
transitions
:to
=>
:closed
,
:from
=>
[
:open
,
:received
]
end
end
test
'should set the name'
do
assert_equal
@state_name
,
new_event
.
name
end
test
'should set the success option'
do
assert_equal
@success
,
new_event
.
success
end
test
'should create StateTransitions'
do
ActiveModel
::
StateMachine
::
StateTransition
.
expects
(
:new
).
with
(
:to
=>
:closed
,
:from
=>
:open
)
ActiveModel
::
StateMachine
::
StateTransition
.
expects
(
:new
).
with
(
:to
=>
:closed
,
:from
=>
:received
)
new_event
end
end
class
EventBeingFiredTest
<
ActiveModel
::
TestCase
test
'should raise an AASM::InvalidTransition error if the transitions are empty'
do
event
=
ActiveModel
::
StateMachine
::
Event
.
new
(
nil
,
:event
)
assert_raise
ActiveModel
::
StateMachine
::
InvalidTransition
do
event
.
fire
(
nil
)
end
end
test
'should return the state of the first matching transition it finds'
do
event
=
ActiveModel
::
StateMachine
::
Event
.
new
(
nil
,
:event
)
do
transitions
:to
=>
:closed
,
:from
=>
[
:open
,
:received
]
end
obj
=
stub
obj
.
stubs
(
:current_state
).
returns
(
:open
)
assert_equal
:closed
,
event
.
fire
(
obj
)
end
end
activemodel/test/cases/state_machine/machine_test.rb
已删除
100644 → 0
浏览文件 @
657d8558
require
'cases/helper'
class
MachineTestSubject
include
ActiveModel
::
StateMachine
state_machine
do
state
:open
state
:closed
end
state_machine
:initial
=>
:foo
do
event
:shutdown
do
transitions
:from
=>
:open
,
:to
=>
:closed
end
event
:timeout
do
transitions
:from
=>
:open
,
:to
=>
:closed
end
end
state_machine
:extra
,
:initial
=>
:bar
do
end
end
class
StateMachineMachineTest
<
ActiveModel
::
TestCase
test
"allows reuse of existing machines"
do
assert_equal
2
,
MachineTestSubject
.
state_machines
.
size
end
test
"sets #initial_state from :initial option"
do
assert_equal
:bar
,
MachineTestSubject
.
state_machine
(
:extra
).
initial_state
end
test
"accesses non-default state machine"
do
assert_kind_of
ActiveModel
::
StateMachine
::
Machine
,
MachineTestSubject
.
state_machine
(
:extra
)
end
test
"finds events for given state"
do
events
=
MachineTestSubject
.
state_machine
.
events_for
(
:open
)
assert
events
.
include?
(
:shutdown
)
assert
events
.
include?
(
:timeout
)
end
end
activemodel/test/cases/state_machine/state_test.rb
已删除
100644 → 0
浏览文件 @
657d8558
require
'cases/helper'
class
StateTestSubject
include
ActiveModel
::
StateMachine
state_machine
do
end
end
class
StateTest
<
ActiveModel
::
TestCase
def
setup
@state_name
=
:astate
@machine
=
StateTestSubject
.
state_machine
@options
=
{
:crazy_custom_key
=>
'key'
,
:machine
=>
@machine
}
end
def
new_state
(
options
=
{})
ActiveModel
::
StateMachine
::
State
.
new
(
@state_name
,
@options
.
merge
(
options
))
end
test
'sets the name'
do
assert_equal
:astate
,
new_state
.
name
end
test
'sets the display_name from name'
do
assert_equal
"Astate"
,
new_state
.
display_name
end
test
'sets the display_name from options'
do
assert_equal
"A State"
,
new_state
(
:display
=>
"A State"
).
display_name
end
test
'sets the options and expose them as options'
do
@options
.
delete
(
:machine
)
assert_equal
@options
,
new_state
.
options
end
test
'equals a symbol of the same name'
do
assert_equal
new_state
,
:astate
end
test
'equals a State of the same name'
do
assert_equal
new_state
,
new_state
end
test
'should send a message to the record for an action if the action is present as a symbol'
do
state
=
new_state
(
:entering
=>
:foo
)
record
=
stub
record
.
expects
(
:foo
)
state
.
call_action
(
:entering
,
record
)
end
test
'should send a message to the record for an action if the action is present as a string'
do
state
=
new_state
(
:entering
=>
'foo'
)
record
=
stub
record
.
expects
(
:foo
)
state
.
call_action
(
:entering
,
record
)
end
test
'should call a proc, passing in the record for an action if the action is present'
do
state
=
new_state
(
:entering
=>
Proc
.
new
{
|
r
|
r
.
foobar
})
record
=
stub
record
.
expects
(
:foobar
)
state
.
call_action
(
:entering
,
record
)
end
end
activemodel/test/cases/state_machine/state_transition_test.rb
已删除
100644 → 0
浏览文件 @
657d8558
require
'cases/helper'
class
StateTransitionTest
<
ActiveModel
::
TestCase
test
'should set from, to, and opts attr readers'
do
opts
=
{
:from
=>
'foo'
,
:to
=>
'bar'
,
:guard
=>
'g'
}
st
=
ActiveModel
::
StateMachine
::
StateTransition
.
new
(
opts
)
assert_equal
opts
[
:from
],
st
.
from
assert_equal
opts
[
:to
],
st
.
to
assert_equal
opts
,
st
.
options
end
test
'should pass equality check if from and to are the same'
do
opts
=
{
:from
=>
'foo'
,
:to
=>
'bar'
,
:guard
=>
'g'
}
st
=
ActiveModel
::
StateMachine
::
StateTransition
.
new
(
opts
)
obj
=
stub
obj
.
stubs
(
:from
).
returns
(
opts
[
:from
])
obj
.
stubs
(
:to
).
returns
(
opts
[
:to
])
assert_equal
st
,
obj
end
test
'should fail equality check if from are not the same'
do
opts
=
{
:from
=>
'foo'
,
:to
=>
'bar'
,
:guard
=>
'g'
}
st
=
ActiveModel
::
StateMachine
::
StateTransition
.
new
(
opts
)
obj
=
stub
obj
.
stubs
(
:from
).
returns
(
'blah'
)
obj
.
stubs
(
:to
).
returns
(
opts
[
:to
])
assert_not_equal
st
,
obj
end
test
'should fail equality check if to are not the same'
do
opts
=
{
:from
=>
'foo'
,
:to
=>
'bar'
,
:guard
=>
'g'
}
st
=
ActiveModel
::
StateMachine
::
StateTransition
.
new
(
opts
)
obj
=
stub
obj
.
stubs
(
:from
).
returns
(
opts
[
:from
])
obj
.
stubs
(
:to
).
returns
(
'blah'
)
assert_not_equal
st
,
obj
end
end
class
StateTransitionGuardCheckTest
<
ActiveModel
::
TestCase
test
'should return true of there is no guard'
do
opts
=
{
:from
=>
'foo'
,
:to
=>
'bar'
}
st
=
ActiveModel
::
StateMachine
::
StateTransition
.
new
(
opts
)
assert
st
.
perform
(
nil
)
end
test
'should call the method on the object if guard is a symbol'
do
opts
=
{
:from
=>
'foo'
,
:to
=>
'bar'
,
:guard
=>
:test_guard
}
st
=
ActiveModel
::
StateMachine
::
StateTransition
.
new
(
opts
)
obj
=
stub
obj
.
expects
(
:test_guard
)
st
.
perform
(
obj
)
end
test
'should call the method on the object if guard is a string'
do
opts
=
{
:from
=>
'foo'
,
:to
=>
'bar'
,
:guard
=>
'test_guard'
}
st
=
ActiveModel
::
StateMachine
::
StateTransition
.
new
(
opts
)
obj
=
stub
obj
.
expects
(
:test_guard
)
st
.
perform
(
obj
)
end
test
'should call the proc passing the object if the guard is a proc'
do
opts
=
{
:from
=>
'foo'
,
:to
=>
'bar'
,
:guard
=>
Proc
.
new
{
|
o
|
o
.
test_guard
}}
st
=
ActiveModel
::
StateMachine
::
StateTransition
.
new
(
opts
)
obj
=
stub
obj
.
expects
(
:test_guard
)
st
.
perform
(
obj
)
end
end
activemodel/test/cases/state_machine_test.rb
已删除
100644 → 0
浏览文件 @
657d8558
require
'cases/helper'
class
StateMachineSubject
include
ActiveModel
::
StateMachine
state_machine
do
state
:open
,
:exit
=>
:exit
state
:closed
,
:enter
=>
:enter
event
:close
,
:success
=>
:success_callback
do
transitions
:to
=>
:closed
,
:from
=>
[
:open
]
end
event
:null
do
transitions
:to
=>
:closed
,
:from
=>
[
:open
],
:guard
=>
:always_false
end
end
state_machine
:bar
do
state
:read
state
:ended
event
:foo
do
transitions
:to
=>
:ended
,
:from
=>
[
:read
]
end
end
def
always_false
false
end
def
success_callback
end
def
enter
end
def
exit
end
end
class
StateMachineSubjectSubclass
<
StateMachineSubject
end
class
StateMachineClassLevelTest
<
ActiveModel
::
TestCase
test
'defines a class level #state_machine method on its including class'
do
assert
StateMachineSubject
.
respond_to?
(
:state_machine
)
end
test
'defines a class level #state_machines method on its including class'
do
assert
StateMachineSubject
.
respond_to?
(
:state_machines
)
end
test
'class level #state_machine returns machine instance'
do
assert_kind_of
ActiveModel
::
StateMachine
::
Machine
,
StateMachineSubject
.
state_machine
end
test
'class level #state_machine returns machine instance with given name'
do
assert_kind_of
ActiveModel
::
StateMachine
::
Machine
,
StateMachineSubject
.
state_machine
(
:default
)
end
test
'class level #state_machines returns hash of machine instances'
do
assert_kind_of
ActiveModel
::
StateMachine
::
Machine
,
StateMachineSubject
.
state_machines
[
:default
]
end
test
"should return a select friendly array of states in the form of [['Friendly name', 'state_name']]"
do
assert_equal
[[
'Open'
,
'open'
],
[
'Closed'
,
'closed'
]],
StateMachineSubject
.
state_machine
.
states_for_select
end
end
class
StateMachineInstanceLevelTest
<
ActiveModel
::
TestCase
def
setup
@foo
=
StateMachineSubject
.
new
end
test
'defines an accessor for the current state'
do
assert
@foo
.
respond_to?
(
:current_state
)
end
test
'defines a state querying instance method on including class'
do
assert
@foo
.
respond_to?
(
:open?
)
end
test
'defines an event! instance method'
do
assert
@foo
.
respond_to?
(
:close!
)
end
test
'defines an event instance method'
do
assert
@foo
.
respond_to?
(
:close
)
end
end
class
StateMachineInitialStatesTest
<
ActiveModel
::
TestCase
def
setup
@foo
=
StateMachineSubject
.
new
end
test
'sets the initial state'
do
assert_equal
:open
,
@foo
.
current_state
end
test
'#open? should be initially true'
do
assert
@foo
.
open?
end
test
'#closed? should be initially false'
do
assert
!
@foo
.
closed?
end
test
'uses the first state defined if no initial state is given'
do
assert_equal
:read
,
@foo
.
current_state
(
:bar
)
end
end
class
StateMachineEventFiringWithPersistenceTest
<
ActiveModel
::
TestCase
def
setup
@subj
=
StateMachineSubject
.
new
end
test
'updates the current state'
do
@subj
.
close!
assert_equal
:closed
,
@subj
.
current_state
end
test
'fires the Event'
do
@subj
.
class
.
state_machine
.
events
[
:close
].
expects
(
:fire
).
with
(
@subj
)
@subj
.
close!
end
test
'calls the success callback if one was provided'
do
@subj
.
expects
(
:success_callback
)
@subj
.
close!
end
test
'attempts to persist if write_state is defined'
do
def
@subj
.
write_state
end
@subj
.
expects
(
:write_state
)
@subj
.
close!
end
end
class
StateMachineEventFiringWithoutPersistence
<
ActiveModel
::
TestCase
test
'updates the current state'
do
subj
=
StateMachineSubject
.
new
assert_equal
:open
,
subj
.
current_state
subj
.
close
assert_equal
:closed
,
subj
.
current_state
end
test
'fires the Event'
do
subj
=
StateMachineSubject
.
new
StateMachineSubject
.
state_machine
.
events
[
:close
].
expects
(
:fire
).
with
(
subj
)
subj
.
close
end
test
'attempts to persist if write_state is defined'
do
subj
=
StateMachineSubject
.
new
def
subj
.
write_state
end
subj
.
expects
(
:write_state_without_persistence
)
subj
.
close
end
end
class
StateMachinePersistenceTest
<
ActiveModel
::
TestCase
test
'reads the state if it has not been set and read_state is defined'
do
subj
=
StateMachineSubject
.
new
def
subj
.
read_state
end
subj
.
expects
(
:read_state
).
with
(
StateMachineSubject
.
state_machine
)
subj
.
current_state
end
end
class
StateMachineEventCallbacksTest
<
ActiveModel
::
TestCase
test
'should call aasm_event_fired if defined and successful for bang fire'
do
subj
=
StateMachineSubject
.
new
def
subj
.
aasm_event_fired
(
from
,
to
)
end
subj
.
expects
(
:event_fired
)
subj
.
close!
end
test
'should call aasm_event_fired if defined and successful for non-bang fire'
do
subj
=
StateMachineSubject
.
new
def
subj
.
aasm_event_fired
(
from
,
to
)
end
subj
.
expects
(
:event_fired
)
subj
.
close
end
test
'should call aasm_event_failed if defined and transition failed for bang fire'
do
subj
=
StateMachineSubject
.
new
def
subj
.
event_failed
(
event
)
end
subj
.
expects
(
:event_failed
)
subj
.
null!
end
test
'should call aasm_event_failed if defined and transition failed for non-bang fire'
do
subj
=
StateMachineSubject
.
new
def
subj
.
aasm_event_failed
(
event
)
end
subj
.
expects
(
:event_failed
)
subj
.
null
end
end
class
StateMachineStateActionsTest
<
ActiveModel
::
TestCase
test
"calls enter when entering state"
do
subj
=
StateMachineSubject
.
new
subj
.
expects
(
:enter
)
subj
.
close
end
test
"calls exit when exiting state"
do
subj
=
StateMachineSubject
.
new
subj
.
expects
(
:exit
)
subj
.
close
end
end
class
StateMachineInheritanceTest
<
ActiveModel
::
TestCase
test
"has the same states as its parent"
do
assert_equal
StateMachineSubject
.
state_machine
.
states
,
StateMachineSubjectSubclass
.
state_machine
.
states
end
test
"has the same events as its parent"
do
assert_equal
StateMachineSubject
.
state_machine
.
events
,
StateMachineSubjectSubclass
.
state_machine
.
events
end
end
class
StateMachineSubject
state_machine
:chetan_patil
,
:initial
=>
:sleeping
do
state
:sleeping
state
:showering
state
:working
state
:dating
event
:wakeup
do
transitions
:from
=>
:sleeping
,
:to
=>
[
:showering
,
:working
]
end
event
:dress
do
transitions
:from
=>
:sleeping
,
:to
=>
:working
,
:on_transition
=>
:wear_clothes
transitions
:from
=>
:showering
,
:to
=>
[
:working
,
:dating
],
:on_transition
=>
Proc
.
new
{
|
obj
,
*
args
|
obj
.
wear_clothes
(
*
args
)
}
end
end
def
wear_clothes
(
shirt_color
,
trouser_type
)
end
end
class
StateMachineWithComplexTransitionsTest
<
ActiveModel
::
TestCase
def
setup
@subj
=
StateMachineSubject
.
new
end
test
'transitions to specified next state (sleeping to showering)'
do
@subj
.
wakeup!
:showering
assert_equal
:showering
,
@subj
.
current_state
(
:chetan_patil
)
end
test
'transitions to specified next state (sleeping to working)'
do
@subj
.
wakeup!
:working
assert_equal
:working
,
@subj
.
current_state
(
:chetan_patil
)
end
test
'transitions to default (first or showering) state'
do
@subj
.
wakeup!
assert_equal
:showering
,
@subj
.
current_state
(
:chetan_patil
)
end
test
'transitions to default state when on_transition invoked'
do
@subj
.
dress!
(
nil
,
'purple'
,
'dressy'
)
assert_equal
:working
,
@subj
.
current_state
(
:chetan_patil
)
end
test
'calls on_transition method with args'
do
@subj
.
wakeup!
:showering
@subj
.
expects
(
:wear_clothes
).
with
(
'blue'
,
'jeans'
)
@subj
.
dress!
:working
,
'blue'
,
'jeans'
end
test
'calls on_transition proc'
do
@subj
.
wakeup!
:showering
@subj
.
expects
(
:wear_clothes
).
with
(
'purple'
,
'slacks'
)
@subj
.
dress!
(
:dating
,
'purple'
,
'slacks'
)
end
end
activerecord/lib/active_record.rb
浏览文件 @
db49c706
...
...
@@ -73,7 +73,6 @@ module ActiveRecord
autoload
:SchemaDumper
autoload
:Serialization
autoload
:SessionStore
autoload
:StateMachine
autoload
:Timestamp
autoload
:Transactions
autoload
:Validations
...
...
activerecord/lib/active_record/state_machine.rb
已删除
100644 → 0
浏览文件 @
657d8558
module
ActiveRecord
module
StateMachine
#:nodoc:
extend
ActiveSupport
::
Concern
include
ActiveModel
::
StateMachine
included
do
before_validation
:set_initial_state
validates_presence_of
:state
end
protected
def
write_state
(
state_machine
,
state
)
update_attributes!
:state
=>
state
.
to_s
end
def
read_state
(
state_machine
)
self
.
state
.
to_sym
end
def
set_initial_state
self
.
state
||=
self
.
class
.
state_machine
.
initial_state
.
to_s
end
end
end
activerecord/test/cases/state_machine_test.rb
已删除
100644 → 0
浏览文件 @
657d8558
require
'cases/helper'
require
'models/traffic_light'
class
StateMachineTest
<
ActiveRecord
::
TestCase
def
setup
@light
=
TrafficLight
.
create!
end
test
"states initial state"
do
assert
@light
.
off?
assert_equal
:off
,
@light
.
current_state
end
test
"transition to a valid state"
do
@light
.
reset
assert
@light
.
red?
assert_equal
:red
,
@light
.
current_state
@light
.
green_on
assert
@light
.
green?
assert_equal
:green
,
@light
.
current_state
end
test
"transition does not persist state"
do
@light
.
reset
assert_equal
:red
,
@light
.
current_state
@light
.
reload
assert_equal
"off"
,
@light
.
state
end
test
"transition does persists state"
do
@light
.
reset!
assert_equal
:red
,
@light
.
current_state
@light
.
reload
assert_equal
"red"
,
@light
.
state
end
test
"transition to an invalid state"
do
assert_raise
(
ActiveModel
::
StateMachine
::
InvalidTransition
)
{
@light
.
yellow_on
}
assert_equal
:off
,
@light
.
current_state
end
end
activerecord/test/models/traffic_light.rb
已删除
100644 → 0
浏览文件 @
657d8558
class
TrafficLight
<
ActiveRecord
::
Base
include
ActiveRecord
::
StateMachine
state_machine
do
state
:off
state
:red
state
:green
state
:yellow
event
:red_on
do
transitions
:to
=>
:red
,
:from
=>
[
:yellow
]
end
event
:green_on
do
transitions
:to
=>
:green
,
:from
=>
[
:red
]
end
event
:yellow_on
do
transitions
:to
=>
:yellow
,
:from
=>
[
:green
]
end
event
:reset
do
transitions
:to
=>
:red
,
:from
=>
[
:off
]
end
end
end
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录