acts_as_state_machine is not concurrent
Here is a short 4 minute screencast in which I show you how the acts as state machine (AASM) gem fails in a concurrent environment, and also how to fix it.
(If embedding doesn’t work or the text is too small to read, you can grab a high resolution version direct from Vimeo)
It’s a pretty safe bet that you want to obtain a lock before all state transitions, so you can use a bit of method aliasing to do just that. This gives you much neater code than the quick fix I show in the screencast, just make sure you understand what it is doing!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
class ActiveRecord::Base def self.obtain_lock_before_transitions AASM::StateMachine[self].events.keys.each do |t| define_method("#{t}_with_lock!") do transaction do lock! send("#{t}_without_lock!") end end alias_method_chain "#{t}!", :lock end end end class Tractor # ... aasm_event :buy do transitions :to => :bought, :from => [:for_sale] end obtain_lock_before_transitions end |
This is a small taste of my DB is your friend training course, that helps you build solid rails applications by finding the sweet spot between stored procedures and treating your database as a hash. July through September I am running full day sessions in the US and UK. Chances are I’m coming to your city. Check it out at http://www.dbisyourfriend.com