这里的aasm版本是3.4.0
aasm在版本3.0.13后就支持ActiveRecord事务了,这在文档中已经说清楚了,但是还有些使用上的细节没有说清楚。
- aasm中使用ActiveRecord事务,所谓的事务是指在一个transition中发生的数据库变化会在出现异常后进行回滚,而且必须是调用带!的aasm方法才会包裹事务,举例说:
class Job < ActiveRecord::Base
include AASM
aasm do
state :sleeping, :initial => true
state :running
event :run do
transitions :from => :sleeping, :to => :running
after :doing_something_to_database
end
end
def doing_something_to_database
...
end
end
如果你调用了:
job.run!
那么状态、doing_something_to_database就都被包裹在了事务中,当里面出现任何异常,所有的数据库操作都会回滚。可以这样做测试:
class Job < ActiveRecord::Base
include AASM
aasm do
state :sleeping, :initial => true
state :running
event :run do
transitions :from => :sleeping, :to => :running
after :doing_something_to_database
before :throw_error
end
end
def doing_something_to_database
...
end
def throw_error
raise 'error!!!'
end
end
- 怎么使用自己的事务,如果自己的业务逻辑涉及的东西比较多,除了状态机的部分,可能还有其他的数据库操作,那么就要自己写事务代码,比如:
Job.transaction do
job.do_abc
job.run!
job.do_xyz
...
end
这个时候就会让人迷惑了,因为这是一个嵌套事务(可以查看这个链接,嵌套事务),我们自己的事务中包了一个aasm提供的事务。这个时候有两种办法来处理: 第一种,官方提供的方法:
class Job < ActiveRecord::Base
include AASM
aasm :requires_new_transaction => false do
...
end
...
end
第二种,不用!方法,但是得自己加save方法,将状态变化保存到数据中
Job.transaction do
job.do_abc
job.run
job.save
job.do_xyz
...
end
另外 before是每次都会执行,不管这个记录状态有没有变化 就算状态改变过了,再调用事,before依然会执行