Cascade delete in Ruby ActiveRecord models?

Jakub Lédl picture Jakub Lédl · Dec 13, 2009 · Viewed 20.8k times · Source

I was following the screencast on rubyonrails.org (creating the blog).

I have following models:

comment.rb

class Comment < ActiveRecord::Base
    belongs_to :post
    validates_presence_of :body # I added this
end

post.rb

class Post < ActiveRecord::Base
    validates_presence_of :body, :title
    has_many :comments
end

Relations between models work fine, except for one thing - when I delete a post record, I'd expect RoR to delete all related comment records. I understand that ActiveRecords is database independent, so there's no built-in way to create foreign key, relations, ON DELETE, ON UPDATE statements. So, is there any way to accomplish this (maybe RoR itself could take care of deleting related comments? )?

Answer

John Topley picture John Topley · Dec 13, 2009

Yes. On a Rails' model association you can specify the :dependent option, which can take one of the following three forms:

  • :destroy/:destroy_all The associated objects are destroyed alongside this object by calling their destroy method
  • :delete/:delete_all All associated objects are destroyed immediately without calling their :destroy method
  • :nullify All associated objects' foreign keys are set to NULL without calling their save callbacks

Note that the :dependent option is ignored if you have a :has_many X, :through => Y association set up.

So for your example you might choose to have a post delete all its associated comments when the post itself is deleted, without calling each comment's destroy method. That would look like this:

class Post < ActiveRecord::Base
  validates_presence_of :body, :title
  has_many :comments, :dependent => :delete_all
end

Update for Rails 4:

In Rails 4, you should use :destroy instead of :destroy_all.

If you use :destroy_all, you'll get the exception:

The :dependent option must be one of [:destroy, :delete_all, :nullify, :restrict_with_error, :restrict_with_exception]