views:

58

answers:

1

Two models, an Account model (has_many :users) and a User model (belongs_to :account, :dependent => :destroy).

My User model has the following:

def protect_master_user
  unless User.find_all_by_account_id_and_is_master(self.account_id, true).count > 1
    false
  end
end

I'm trying to protect the master users from being deleted. How can I override this if the parent (Account) is deleted? I've tried :dependent => :destroy and :delete to no avail.

EDIT: fixed code.

+1  A: 

There are two ways to do this: has_many :users, :dependent => :delete_all, or with an additional custom callback in Accounts. The :delete_all method is simpler, but not advised, because it means that none of your other call backs will happen on the user record.

The correct solution is a custom before_destroy callback in Account, working in tandem with the callback in user.

class Account < ActiveRecord::Base
  has_many :users 

  before_destroy :destroy_users
  protected
    def destroy_users
      users.each do |user|
        u.account_id = nil
        u.destroy
      end
    end

end

class User < ActiveRecord::Base
  belongs_to :account

  before_destroy :protect_master_user

  protected
    def protect_master_user
      unless account_id.nil? ||! master || 
        User.find_all_by_account_id_and_master(self.account_id, true).count > 1
        errors.add_to_base "Cannot remove master user."
        return false
      end
    end
end

If the account.id is nil we short circuit the unless and the destroy continues. Same goes for if the user is not a master user. Why do we need to check if there's more than one master user if the object being destroyed isn't a master user either?

Again, delete could be used in place of destroy. But it skips any *_destroy callbacks you have or will ahve in the future.

EmFi
Thanks for your reply, however this is not working for me. What you suggested makes sense, but I think User destroy is first. Any other ideas?
TMB
Weird. I thought I had it working yesterday. I've updated it to use a custom call back and described why a :dependent => :delete_all is no good.
EmFi
Thanks, I had come up with the same solution but wasn't sure if deleting users from the Account model was the way to go. Thanks again.
TMB