implicit Transactions and after_save callback

Hi group,

I have a Problem with ActiveRecord. I´m using SQL-Queries in the after_save-Callbacks which assert, that the change in the db already took place. But this is not the case, because we´re still in the transaction.

As far as I know, there is no callback which is called AFTER a commit although this i think this would be very attractive. What can I do here?

Here is the Problem: I have the class Event, Resources and ResourceUses. Think of them as lessons (Events) and Teachers and Rooms (Resources).

Hi group,

I have a Problem with ActiveRecord. I´m using SQL-Queries in the after_save-Callbacks which assert, that the change in the db already took place. But this is not the case, because we´re still in the transaction.

As far as I know, there is no callback which is called AFTER a commit although this i think this would be very attractive. What can I do here?

Here is the Problem: I have the class Event, Resources and ResourceUses. Think of them as lessons (Events) and Teachers and Rooms (Resources). ----------------------------------------- class Event < ActiveRecord::Base   has_many :resource_uses, :dependent => :destroy   has_many :resources, :through => :resource_uses

  validates_presence_of :date   validates_presence_of :from   validates_presence_of :to

-------------------------------------------- The Class "ResourceUse" has to check for Collisions based on the time- data of the associated events. So in the after_save Callback, I run a SQL-Query (in an instance-method of ResourceUse) to check for collisions.

Exactly: I have to do this for all ResourceUse-Instances which had collisions with the event BEFORE the event saved.

How could this be solved, any hints?

I think the simplest solution is a lock on the resource while preparing your reservation, e.g.:

Whatever.transaction do

  # issue "select for update"; grab an exclusive lock on this row   # until end of transaction. any other tx trying to lock the same   # row will have to wait until it's released   resource = Resource.find(..., :lock => true)

  # check for collisions and schedule ResouceUse if there's no conflict

end # commit, freeing the lock on resource

Just be aware of deadlock issues; you don't want transactions to lock multiple resources (if you must, make sure you always lock rows in the same order -- but do try to find something more general to grab a single lock on).

I think you could also set a transaction isolation level that lets you see uncommitted writes, create your reservation and then check for conflicts before commiting. Doubt this will work on all DBs.

HTH, Isak

Thanks for clearing this up for me. I don´t like the idea do do it with locks, so I´ll try to do it with the low isolation level in combination with optimistic locking.

Kim