如何用Devise“软删除”用户

我目前在Rails项目中使用Devise进行用户注册/authentication。 当用户想要取消他们的帐户时,用户对象被销毁,这使我的应用程序处于不希望的状态。

实施“软删除”最简单的方法是什么,即只删除个人数据并将用户标记为已删除? 我仍然想保留所有的logging协会。

我假设我将不得不首先为用户引入一个新的“删除”列。 但是,我坚持用户的configuration文件视图中的这个默认代码:

<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :confirm => "Are you sure?", :method => :delete %>.</p> 

我在哪里可以find:delete方法? 我应该如何覆盖默认的devise方法?

我可以build议覆盖你的用户模型的destroy方法,只是做update_attribute(:deleted_at, Time.current) (而不是实际销毁),但是这种偏离标准的API可能在将来变得繁重,所以这里是如何修改控制器。

Devise有一大堆默认的控制器。 定制它们的最好方法是创build自己的控制器,inheritance相应的devise控制器。 在这种情况下,我们正在讨论Devise::RegistrationsController – 这很容易通过查看源代码来识别。 所以创build一个新的控制器。

 class RegistrationsController < Devise::RegistrationsController end 

现在我们有我们自己的控制器完全inheritance所有devise提供的逻辑。 下一步是告诉devise使用它,而不是默认的。 在你的路线你有devise_for线。 应该更改为包含注册控制器。

 devise_for :users, :controllers => { :registrations => 'registrations' } 

这看起来很奇怪,但这是有道理的,因为默认情况下是“devise/注册”,而不是简单的“注册”。

下一步是重写注册控制器中的destroy操作。 当你使用registration_path(:user), :method => :delete – 这就是它连接的地方。 destroy注册destroy行为。

目前devise如下。

 def destroy resource.destroy set_flash_message :notice, :destroyed sign_out_and_redirect(self.resource) end 

我们可以改用这个代码。 首先让我们将新方法添加到User模型。

 class User < ActiveRecord::Base def soft_delete # assuming you have deleted_at column added already update_attribute(:deleted_at, Time.current) end end # Use this for Devise 2.1.0 and newer versions class RegistrationsController < Devise::RegistrationsController def destroy resource.soft_delete Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name) set_flash_message :notice, :destroyed if is_navigational_format? respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name) } end end # Use this for older Devise versions class RegistrationsController < Devise::RegistrationsController def destroy resource.soft_delete set_flash_message :notice, :destroyed sign_out_and_redirect(resource) end end 

现在你应该一切设置。 使用范围来过滤已删除的用户。

添加到hakunin的答案 :

要防止“软删除”用户login,请覆盖active_for_authentication? 在您的User模型上:

 def active_for_authentication? super && !deleted_at end 

您可以使用acts_as_paranoid作为您的用户模型,它设置deleted_at而不是删除对象。

在Devise wiki页面的Soft Delete a Devise User Account上可以find完整的教程。

概要:
1.添加“deleted_at”DATETIME列
2.覆盖用户/注册#在您的路线销毁
3.覆盖用户/注册#在注册控制器中销毁
4.使用soft_delete更新用户模型并检查用户是否处于活动状态
5.添加自定义删除消息