:dependent => :raise

June 22nd, 2007

Ever get woken up at night worrying about referential integrity? "What if someone deletes a Client and we end up with loads of orphaned Tickets in the database!" Just me? Ok...

It's an easy problem to solve, but why not try handling it like this:

class Person < ActiveRecord::Base
  has_many :books, :dependent => :raise
end

>> me = Person.find_by_name("steve")
>> me.destroy
ActiveRecord::HasManyDependentRecordsError: Dependent Book records for Person

Just handle the exception and you're sorted.

Download the plugin here: http://www.stephenbartholomew.co.uk/assets/2007/6/22/dependent_raise.zip

5 Responses to “:dependent => :raise”

  1. Jody Baty Says:

    Sounds like a good way to approach this issue. I'm wondering, though, what sort of things would you do in handling the exception? Is there an advantage in using an exception rather than just using :dependent => :true?

  2. Stephen Says:

    Jody: :dependent => :true is a depreciated method that has been replaced by :dependent => :destroy. This causes dependent records to be deleted if the parent record is destroyed.

    :dependent => :raise is for situations where you want to ensure that a parent record cannot be removed if it has children.

    The particular application that I wrote this for was for a client who had a list of Companies, Users and Jobs. They needed to keep a record of every job and as such needed to make sure that companies and users that had jobs assigned to them could not be removed. Of course you could achieve this with user notices, but this method ensures referential integrity on an application level.

  3. nope Says:

    What are the benefits to re-implement SQL constraints like ON (DELETE/UPDATE) (CASCADE/SET NULL/RESTRICT/NO ACTION) and triggers in pure Ruby ActiveRecord (except app-level results caching)?

    Guys, tell me please what's the complexity of DB schema (tables/views/constraints) in your projects having numerous non-modified installations in all SQL-DBMS flavours, that ActiveRecord supports?

    Can you convince me, that no-code-change database independence is really reachable and reasonable?

    Are we approaching the day "Imagine, Neo, there's no DB. Just take a red pill, we use them for REST" :))) ???

  4. Stephen Says:

    nope: To be honest I think it's quite often personal preference. Personally, I work with a small development team and we all work on the whole system. We have a preference for application level logic like this and use the database merely to store data.

    In larger teams and applications it is quite different. You may have multiple applications accessing the database and therefore require certain logic to be contained in the database. You may also have DBA to manage database interactions who will therefore want to maintain a certain level of control.

    As such, I'm not going to try to convince you either way - you do what you want to do - it's perfectly acceptable to me to use SQL constraints. At the moment, I just prefer to do it in my models :0)

  5. Brandon Keepers Says:

    Stephen,

    I think this plugin is a great idea. I've been contemplating this problem for a while and often just do :dependent => :destroy, hoping the user knows what they're doing. With this, I could have a default rescue action that sends the user to a page asking them if they really want to destroy all the associated records.

    Thanks for sharing!

Sorry, comments are closed for this article.