# Preventing destory when grandchildren records exist?

**URL:** <https://www.ruby-forum.com/t/preventing-destory-when-grandchildren-records-exist/87190>\
**Category:** Rails\
**Created:** [February 28, 2007, 7:42pm UTC](https://www.ruby-forum.com/t/preventing-destory-when-grandchildren-records-exist/87190 "2007-02-28T19:42:45Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![robtotheb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/db5fbb/32.png) [@robtotheb](https://www.ruby-forum.com/u/robtotheb)\
**Post date:** [February 28, 2007, 7:42pm UTC](https://www.ruby-forum.com/t/preventing-destory-when-grandchildren-records-exist/87190/1 "2007-02-28T19:42:45Z")

</div>

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  
end  
end  
end

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  
products”  
return false  
end  
# raise “Can’t destroy a category having products” unless  
self.products.empty?  
end  
end

class Product \< ActiveRecord::Base  
belongs\_to :category  
end

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:  
Group=\>Category=\>Product  
Author=\>Post=\>Comment  
House=\>Room=\>Furniture

I found a thread on the Rails-core list ([http://wrath.rubyonrails.org/](http://wrath.rubyonrails.org/)  
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://  
[dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html](http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html)),  
but I don’t know if that led to this ticket (http://  
[dev.rubyonrails.org/ticket/3837](http://dev.rubyonrails.org/ticket/3837)) which has a patch which is currently  
available as a plugin. (These are concerned with just the one-level  
dependency however.)

-Rob

Rob B. [http://agileconsultingllc.com](http://agileconsultingllc.com)  
removed\_email\_address@domain.invalid
