Sometimes, you just want to make your database objects threadsafe and run parallel/concurrent tasks on them without making a mess.
Imagine the following situation:
What would happend if two jobs want to update the same record, at the same time?
Wouldn't be lovely if the 2nd job skips the first record if the 1st job is working on it?
Thats why I created the following concern:
1 # app/models/concerns/lockable.rb 2 3 require 'active_support/concern' 4 5 module Lockable 6 @locked = false 7 8 def locked? 9 @locked == true 10 end 11 12 def lock! 13 raise Exception, 'You should define the lock! method inside your class' 14 end 15 16 def unlock! 17 raise Exception, 'You should define the unlock! method inside your class' 18 end 19 20 def while_locked 21 return false if locked? 22 23 lock! 24 needs_unlock = true 25 26 yield 27 ensure 28 unlock! if needs_unlock 29 end 30 end
Here is the Lockable concern specs if you're wondering: gist.github.com/TiuTalk/10433564
Remember to override the persistence methods on your model, like this:
1 class MyModel < ActiveRecord::Base 2 include Lockable 3 4 def lock! 5 update_attribute(:locked, true) 6 end 7 8 def unlock! 9 update_attribute(:locked, false) 10 end 11 end
And you can wrap your code with the while_locked method, like this:
1 object = MyModel.find(12) 2 3 object.while_locked do 4 object.some_serious_shit! 5 end
With this, you can have multiple simultaneous processes running on your database records without one messing with the other! How fancy is that?