Can I use the optimistic object lock to protect my associations?

We are having problems with race conditions in our rails application. Here is some (simplified) code before I explain:

class Message < ActiveRecord::Base
  belongs_to :question
end

class Question < ActiveRecord::Base
  has_many :messages

  def create_or_update_sending_message
    sending_message = messages.detect {|m| m.status == 'sending'}
    sending_message ||= messages.create :status => 'sending'
    sending_message
  end

  def validate
    errors.add_to_base('cannot have multiple sending messages') if messages.select {|m| m.status == 'sending'}.count > 1
  end
end

What happens in what is create_or_update_sending_messagecalled from two processes. Both treat the message collection as empty, so both create a new message. Then the third process loads the question, modifies it, tries to save it, and we get an error thrown in a place where there is no real problem.

I can come up with several ways to avoid this if we develop from scratch, but, unfortunately, is create_or_update_sending_messagetoo deep in legacy code to be practical.

. , - .

?

def create_or_update_sending_message
  self.optimistically_lock do |lock|
    sending_message = messages.detect {|m| m.status == 'sending'}
    sending_message ||= messages.create_with_optimistic_lock lock, :status => 'sending'
    sending_message
  end
end

?

+3

All Articles