Read my latest article: 8 things I look for in a Ruby on Rails app (posted Thu, 06 Jul 2017 17:59:00 GMT)

New Active Record Options for Associations

Posted by Wed, 19 Oct 2005 23:00:00 GMT

7 comments Latest by dfhsdfh Mon, 21 Aug 2006 10:51:08 GMT

Two months ago today I posted about a bug in Active Record. A bug that reminded me to remain cautious about how much trust I put into a database abstraction layer. I am happy to now say that this particular bug has been fixed, and I got to help! In the process, I also got to add some new features. (see my original rant, Active Record, I love U but I still trust my database server a tiny bit more.

I discovered this bug when I was working on a chapter in my book on Active Record. I’m known to gladly take advantage of database constraints and triggers, and it was when I decided to test my code without these constraints, I discovered the bug. “Hey, Active Record isn’t doing what it’s supposed to!” I’ve since had a number of people ask me if what a more pragmatic way to work around this issue is, rather than go my route by adding a constraint/trigger.

You can now DO AWAY with ON DELETE CASCADE! (sort of)

The new release of Rails 1.0 Release Candidate includes some new options for the has_many and has_one declarations.

Previously, you could do the following:

class Customer < ActiveRecord::Base
  has_many :orders, :dependent => true
end

This was supposed to nullify the dependent records, but it didn’t!

My patch not only fixes this, but also gives more control with what :dependent does. Now, you can pass the :dependent option to the has_many and has_one declarations with either :nullify or :destroy. This has a similar affect as ON DELETE CASCADE in those fancy RDBMs like PostgreSQL.

Let’s take a closer look at these new options:

has_one

A spider has_one web, and the web belongs_to one spider. If you destroy the spider, you would most likely want to destroy the web as well.

class Spider < ActiveRecord::Base
  has_one :web, :dependent => :destroy
end

On the other hand, in the case of a snail that has_one shell (and the one shell belongs_to the snail), if you destroy the snail, you may want to keep the shell. Remember, your crazy Aunt Ruby collects snail shells.

class Snail < ActiveRecord::Base
  has_one :shell, :dependent => :nullify
end

Now, for every snail we destroy, the shells, though once dependent on the snail, are now available for Aunt Ruby.

has_many

The same rules apply to the has_many association. Most people assume that if you destory a beehive that you would destroy all the bees. I’d like to think that they wander around until they find a new beehive to join. So, we can :nullify their relationship when the beehive is destroyed, thus making them homeless, but available for future hives.

class Beehive < ActiveRecord::Base
  has_many :bees, :dependent => :nullify
end

Sadly, some people might want to destroy the bees along with the destruction of the beehive. So, those people can pass the :dependent option, :destroy.

class Beehive < ActiveRecord::Base
  has_many :bees, :dependent => :destroy
end

Don’t worry, your usage of :dependent => true will now work, even though it wasn’t working before.

I’m going to try to put more trust into Active Record now, and I hope that this new addition to the library finds itself useful for you. :-)

Take a peak at the cool new features in the latest version of Rails and see the Active Record CHANGELOG for more information.

Enjoy!

Older posts: 1 2