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.
355142cdc86e67843026a2c8b85ab53a?d=identicon&s=25 k9ert (Guest)
on 2007-05-08 23: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/
5233478c51a92b6a1a5c970cbf3a42f3?d=identicon&s=25 Isak Hansen (Guest)
on 2007-05-09 11:40
(Received via mailing list)
On 5/8/07, k9ert <k9ert@gmx.de> 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
355142cdc86e67843026a2c8b85ab53a?d=identicon&s=25 k9ert (Guest)
on 2007-05-10 19: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.