Forum: Ruby on Rails Preventing destory when grandchildren records exist?

Announcement (2017-05-07): is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see and for other Rails- und Ruby-related community platforms.
Ef3aa7f7e577ea8cd620462724ddf73b?d=identicon&s=25 Rob Biedenharn (Guest)
on 2007-02-28 19:42
(Received via mailing list)
OK, I'm hoping there's a better way to do this, but searching returns
many more old hits than "current" ones.

I am working on an application that has Products belong to a Category
and categories belong to a Group.  I want to restrict the removal of
a Category when it still has Products.  I also want to restrict the
removal of a Group if any of it's categories can't be removed.

class Group < ActiveRecord::Base
   before_destroy :ensure_no_categories_with_products
   has_many :categories, :dependent => :destroy

   def ensure_no_categories_with_products
     unless self.categories.all? {|c| c.products.empty?}
       self.errors.add_to_base "Can't destroy a group referenced by a
category having products"
       return false

class Category < ActiveRecord::Base
   belongs_to :group
   before_destroy :ensure_no_products
   has_many :products

   def ensure_no_products
     unless self.products.empty?
       self.errors.add_to_base "Can't destroy a category having
       return false
     # raise "Can't destroy a category having products" unless

class Product < ActiveRecord::Base
   belongs_to :category

As a side note, I couldn't find definitive guidance on whether
returning false or raising an exception was "better", but returning
false ended up working out better for my controllers.

So here's the big question:  It feels wrong to duplicate the
condition "unless self.categories.all? {|c| c.products.empty?}" in
the Group model, but I'm not sure changing it to "unless
self.categories.all? {|c| c.ensure_no_products }" feels any better.

I realize it's a bit asymmetric letting a Group be removed if there
are existing Categories that happen to be Productless, but I'm OK
with the :dependent => :destroy taking care of that.

What I'd love to know is if there's a better way.  I can see this
same kind of relationship other places:

I found a thread on the Rails-core list (
pipermail/rails-core/2006-July/001986.html) that offered a similar
solution via a new :dependent=>:restrict option on has_many (to mimic
the RESTRICT option in some SQL dialects such as MySql http://,
but I don't know if that led to this ticket (http:// which has a patch which is currently
available as a plugin. (These are concerned with just the one-level
dependency however.)


Rob Biedenharn
This topic is locked and can not be replied to.