ASPN ActiveState Programmer Network
ActiveState
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups


Recent Messages
List Archives
About the List
List Leaders
Subscription Options

View Subscriptions
Help

View by Topic
ActiveState
.NET Framework
Open Source
Perl
PHP
Python
Tcl
Web Services
XML & XSLT

View by Category
Database
General
SOAP
System Administration
Tools
User Interfaces
Web Programming
XML Programming


MyASPN >> Mail Archive >> ruby-rails
ruby-rails
[Rails] habtm and before_destroy
by Sam Kirchmeier other posts by this author
Aug 29 2005 11:19AM messages near this date
Re: [Rails] Date Types in Unit Tests | [Rails] mysql problem?
The habtm association is causing a little trouble for me, and I'm
having trouble coming up with an elegant alternative way to skin my
cat.

It automatically registers a before_destroy callback that deletes the
appropriate records from the join table. The problem is that this
callback is called before any before_destroy code I add later.

Imagine the old standby example for, ahem, creatively challenged
people like myself: an online gallery with albums and photos. Photos
habtm albums and albums habtm photos. If I destroy an album, then I
also want to destroy its photos, but only the photos that are not in
any other albums.

This is pretty easily accomplished in a before_destroy block that
checks the albums_photos join table:

before_destroy :destroy_and_update_photos

def destroy_and_update_photos
  # destroy photos that are only in this album
  # update photos that are in multiple albums
  if self.photos_count >  0
    photo_ids = self.photos.map{ |photo| photo.id }.join(',')
    Photo.destroy_all "id IN (#{photo_ids}) AND albums_count = 1"
    Photo.update_all 'albums_count = albums_count - 1', "id IN
(#{photo_ids}) AND albums_count >  1"
  end
end

The problem is that before the above code is called, the habtm
association slipped in its own before_destroy block to delete all of
the records in the join table that pertain to the album being
destroyed. Since the data is gone, there's no way to know which photos
were in this album!

Using script/console, I can see this:
> > Album.read_inheritable_attribute(:before_destroy)
=>  ["self.connection.delete(%{DELETE FROM albums_photos WHERE album_id
= \#{self.quoted_id}})", :destroy_and_update_photos]

(Note: the :before_destroy attribute looks like this regardless of
whether you use the before_destroy macro as I have or overwrite the
method.) One solution would be to manually overwrite this inheritable
attribute, but I'd rather not mess with the ActiveRecord internals if
possible.

Someone out there must have run into this problem before me, but I've
come to the conclusion that the gmane search engine is pretty
crappy...well, that or I'm pretty crappy at using it.

Sam
_______________________________________________
Rails mailing list
Rails@[...].org
http://lists.rubyonrails.org/mailman/listinfo/rails

Privacy Policy | Email Opt-out | Feedback | Syndication
© ActiveState Software Inc. All rights reserved