aasm和ActiveRecord事务

这里的aasm版本是3.4.0html

aasm在版本3.0.13后就支持ActiveRecord事务了,这在文档中已经说清楚了,可是还有些使用上的细节没有说清楚。数据库

  1. 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

若是你调用了:api

job.run!

那么状态、doing_something_to_database就都被包裹在了事务中,当里面出现任何异常,全部的数据库操做都会回滚。能够这样作测试:ruby

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
  1. 怎么使用本身的事务,若是本身的业务逻辑涉及的东西比较多,除了状态机的部分,可能还有其余的数据库操做,那么就要本身写事务代码,好比:
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方法,将状态变化保存到数据中ui

Job.transaction do
    job.do_abc
    job.run
    job.save
    job.do_xyz
    ...
end

另外 before是每次都会执行,无论这个记录状态有没有变化 就算状态改变过了,再调用事,before依然会执行code

相关文章
相关标签/搜索