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