Destroy ordering with associations... reasoning?

Hi,

I’m having a problem understanding why rails calls the ‘before_destroy’
methods in the ordering as as follows (w/contrived ex)…

class User
belongs_to :group

def before_destroy
# don’t delete the user if they’re named ‘test’
false if name == ‘test’
end
end

class Group
has_many :users, :dependent => :destroy

def before_destroy
# change all names to ‘bob’ so that we can make sure this group can
be deleted
User.update_all “name = ‘bob’”
end
end

If I call destroy on the group…

Group.find(:first).destroy

The ordering of operations is…
before_destroy is called for every user in the group first
before_destroy is called for the group

To me, before_destroy for the group should be called first to do any
“prep” as I have in my example. The method is named for what it should
be doing… call the method BEFORE the object is DESTROYed. According
to the ordering I’m seeing, ‘before_destroy’ is being called after the
destroy process has already begun. So why is this not the case? The
docs say this method is called before he destroy method is called; is
this not correct?

Confused,
Andrew

Hi Andrew,

Andrew K. wrote:

If I call destroy on the group…

Group.find(:first).destroy

The ordering of operations is…
before_destroy is called for every user in the group first
before_destroy is called for the group

The order is driven by the relationships you’ve specified. The
:dependent
=> destroy on Group tells Rails to destroy any User child records
before
trying to destroy User records. That’s a basic referential integrity
constraint.

hth,
Bill

Bill W. wrote:

Hi Andrew,

Andrew K. wrote:

If I call destroy on the group…

Group.find(:first).destroy

The ordering of operations is…
before_destroy is called for every user in the group first
before_destroy is called for the group

The order is driven by the relationships you’ve specified. The
:dependent
=> destroy on Group tells Rails to destroy any User child records
before
trying to destroy User records. That’s a basic referential integrity
constraint.

hth,
Bill

So I suppose my solution is to remove the :dependent option and manually
destroy all users in the groups before_destroy callback after I’ve done
the “prep”.

So this now…

class Group
has_many :users

def before_destroy
# change all names to ‘bob’ so that we can make sure this group can
be deleted
User.update_all “name = ‘bob’”
# destroy all users
Users.destroy_all
end
end

I guess I’m looking for a different callback that doesn’t exist that
truly gets called before Model.destroy regardless of associations.

Thanks,
Andrew