supporting ActiveRecord transactions when firing an event

This commit is contained in:
Thorsten Böttger 2012-10-24 21:03:09 +13:00
parent 4002c8198c
commit 05d64cdf37
8 changed files with 72 additions and 3 deletions

View File

@ -1,5 +1,9 @@
# CHANGELOG
## 3.0.13
* supporting ActiveRecord transactions when firing an event
## 3.0.12
* aasm_from_states_for_state now supports to filter for specific transition

View File

@ -5,7 +5,13 @@ This package contains AASM, a library for adding finite state machines to Ruby c
AASM started as the acts_as_state_machine plugin but has evolved into a more generic library
that no longer targets only ActiveRecord models. It currently provides adapters for
[ActiveRecord](http://api.rubyonrails.org/classes/ActiveRecord/Base.html) and
[Mongoid](http://mongoid.org/).
[Mongoid](http://mongoid.org/), but it can be used for any Ruby class, no matter its
parent class.
### Transaction support
Since version 3.0.13 AASM supports ActiveRecord transactions. So whenever a transition
callback fails, all changes to any database record are rolled back.
## Features ##

View File

@ -7,7 +7,7 @@ module AASM
AASM::StateMachine[base] = AASM::StateMachine.new('')
end
AASM::Persistence.set_persistence(base)
super
super
end
module ClassMethods
@ -72,7 +72,7 @@ module AASM
def aasm_human_event_name(event)
AASM::SupportingClasses::Localizer.new.human_event_name(self, event)
end
end
end # ClassMethods
# this method does what? does it deliver the current state?
def aasm_current_state

View File

@ -149,6 +149,12 @@ module AASM
aasm_enter_initial_state if send(self.class.aasm_column).blank?
end
def aasm_fire_event(name, options, *args)
transaction do
super
end
end
end
module WriteStateWithoutPersistence

26
spec/models/transactor.rb Normal file
View File

@ -0,0 +1,26 @@
require 'active_record'
class Transactor < ActiveRecord::Base
belongs_to :worker
include AASM
aasm :column => :status do
state :sleeping, :initial => true
state :running, :before_enter => :start_worker, :after_enter => :fail
event :run do
transitions :to => :running, :from => :sleeping
end
end
private
def start_worker
worker.update_attribute(:status, 'running')
end
def fail
raise StandardError.new('failed on purpose')
end
end

2
spec/models/worker.rb Normal file
View File

@ -0,0 +1,2 @@
class Worker < ActiveRecord::Base
end

View File

@ -11,6 +11,17 @@ ActiveRecord::Schema.define(:version => 0) do
t.string "status"
end
create_table "transactors", :force => true do |t|
t.string "name"
t.string "status"
t.integer "worker_id"
end
create_table "workers", :force => true do |t|
t.string "name"
t.string "status"
end
create_table "invalid_persistors", :force => true do |t|
t.string "name"
t.string "status"

View File

@ -1,6 +1,7 @@
require 'rubygems'
require 'active_record'
require 'logger'
require 'spec_helper'
load_schema
@ -317,4 +318,17 @@ describe 'transitions with persistence' do
persistor.should_not be_sleeping
end
describe 'transactions' do
it 'should rollback all changes' do
worker = Worker.create!(:name => 'worker', :status => 'sleeping')
transactor = Transactor.create!(:name => 'transactor', :worker => worker)
transactor.should be_sleeping
worker.status.should == 'sleeping'
lambda {transactor.run!}.should raise_error(StandardError, 'failed on purpose')
transactor.should be_running
worker.reload.status.should == 'sleeping'
end
end
end