Forum: Ruby on Rails implicit Transactions and after_save callback

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
k9ert (Guest)
on 2007-05-09 01:24
(Received via mailing list)
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?


Kim

http://rubyforge.org/projects/resman/
Isak H. (Guest)
on 2007-05-09 13:40
(Received via mailing list)
On 5/8/07, k9ert <removed_email_address@domain.invalid> wrote:
> here?
>   validates_presence_of :from
>
> 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
k9ert (Guest)
on 2007-05-10 21:43
(Received via mailing list)
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
This topic is locked and can not be replied to.