In the Ruby on Rails application I am working on, I have a model ‘Album’ and a model ‘Photo’. As you have guessed, each album can have many photos. This is a typical one-to-many relationship and can be coded like this:
class Album < ActiveRecord::Base has_many :photos end class Photo < ActiveRecord::Base belongs_to :album end [/sourcecode] Since I want to have 'delete album' function in my application, I coded a destroy method in the my album controller. [sourcecode language='ruby'] class AlbumsController < ApplicationController def destroy @album = @account.albums.find(params[:id]) @album.photos.destroy_all @album.destroy end end [/sourcecode] Nothing fancy here. A simple "delete the photos first before you delete the album" operation. This code has been in my application for several months and I even used the pattern in my other controllers. A while ago I was working on the admin pages and I was reviewing another 'destroy' method when I thought why should my "destroy" method explicity destroy the child records in my controller. My controller should know as little as possible (or none at all) how my models are related. My initial idea is to let the 'Album' model handle the deletion of the 'Photo' records. I thought a 'before_destroy' callback would do the trick. Just to be sure there are no gotchas, I looked it up in the Ruby on Rails API. I just found out, there is a simpler way of "delete the photos first before you delete the album". In my 'Album' model, I included the 'dependent' option in the 'has_many' association. [sourcecode language='ruby'] class Album <ActiveRecord::Base has_many :photos, :dependent => :destroy end
All I need to do now is simply call ‘@album.destroy’ in my controller and all child photos will be deleted. Sweet.
Aside from the ‘dependent’ option, there is also the ‘exclusively_dependent’ which can delete the child records in a single SQL statement (which is faster than traversing each child record) on the condition that the child table has no hook methods on deletion and it is used only by the parent table.