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