Question

I have two models one of them is a User, and another Comments. Comments belong to User.

class User < ActiveRecord::Base
    act_as_paranoid
    has_many :comments
end

class Comment < ActiveRecord::Base
    belongs_to :user
end

When I do user.delete in my controller I get the expected result of the deleted_at column being set and the record being hidden.

My problem is the Comment associations for the user are set to null. So now on the site it shows no user owning the comment. I'd like the comment to still show the user's name not be "None" or "Anonymous" etc.

Looking at the source on github https://github.com/goncalossilva/rails3_acts_as_paranoid/blob/rails3.2/lib/acts_as_paranoid/core.rb it seems to call run_callbacks which in turn results in Rails 3 falling back to Nullify default for associations.

In my case I just want the user account to be closed off when deleted. Not showing up in queries anymore so that Authlogic will deny them and the User index page won't show them. But still allowing everything a user owns to still be owned by them (since they may come back, etc.).

Is there a better way to do this then acts_as_paranoid?

Was it helpful?

Solution

Rather then go to the trouble of overriding the destroy method I created a close method that simply sets closed_at to a timestamp. If you set default scope to something like:

default_scope { where("closed_at IS NULL") }

Then the model won't show up to any queries including User.All. You can delete the scope to get a full query essentially I took these ideas from act_as_paranoid but much more simplified. The problem is that then even though the Comments still have user_id set, the default scope runs with any association load. So say

c = Comment.first
c.user

That will output nil if user_id is a closed account. In my case the easiest solusion was to remove default scoping and modify my Authlogic function to:

def self.find_by_username_or_email(login)
  u = User.find(:first, :conditions => ["lower(username) = ?", login.downcase]) || User.find_by_email(login)
  return u unless u.closed_at  
end

This way closed accounts can't login. Anywhere I list out users in my views I used a hide_closed scope.

Not sure if this was the best most elegant solution. But for my purposes it works.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top