I currently use Devise for user registration/authentication in a Rails project. When a user wants to cancel their account, the user object is destroyed, which leaves my application in an undesired state.
What is the easiest way to implement a “soft delete”, i.e. only removing personal data and marking the user as deleted? I still want to keep all record associations.
I assume I will have to first introduce a new “deleted” column for users. But then I am stuck with this default code in the user’s profile view:
<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :confirm => "Are you sure?", :method => :delete %>.</p>
Where can I find the :delete method? How should I overwrite the default Devise methods?
I could advise overriding
destroymethod on your User model to simply doupdate_attribute(:deleted_at, Time.current)(instead of actually destroying), but this deviation from standard API could become burdensome in the future, so here’s how to modify the controller.Devise has a bunch of default controllers out of the box. The best way to customize them is to create your own controller inheriting the corresponding devise controller. In this case we are talking about
Devise::RegistrationsController— which is easily recognized by looking at source. So create a new controller.Now we have our own controller fully inheriting all the devise-provided logic. Next step is to tell devise to use it instead of the default one. In your routes you have
devise_forline. It should be changed to include registrations controller.This seems strange, but it makes sense because by default it’s ‘devise/registrations’, not simply ‘registrations’.
Next step is to override the
destroyaction in registrations controller. When you useregistration_path(:user), :method => :delete— that’s where it links. Todestroyaction of registrations controller.Currently devise does the following.
We can instead use this code. First let’s add new method to
Usermodel.Now you should be all set. Use scopes to filter out deleted users.