Ruby-on-rails 如何使用设计“软删除”用户
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5140643/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to "soft delete" user with Devise
提问by slhck
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.
我目前在 Rails 项目中使用 Devise 进行用户注册/身份验证。当用户想要取消他们的帐户时,用户对象被销毁,这使我的应用程序处于不希望的状态。
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 :deletemethod? How should I overwrite the default Devise methods?
我在哪里可以找到:delete方法?我应该如何覆盖默认的设计方法?
回答by Max Chernyak
I could advise overriding destroymethod on your User model to simply do update_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.
我可以建议destroy您的 User 模型上的覆盖方法简单地执行update_attribute(:deleted_at, Time.current)(而不是实际销毁),但是这种与标准 API 的偏差在未来可能会变得很麻烦,所以这里是修改控制器的方法。
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.
Devise 有一堆开箱即用的默认控制器。自定义它们的最佳方法是创建自己的控制器,继承相应的设计控制器。在这种情况下,我们谈论的是Devise::RegistrationsController- 通过查看来源很容易识别。所以创建一个新的控制器。
class RegistrationsController < Devise::RegistrationsController
end
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.
现在我们有了自己的控制器,完全继承了设计提供的所有逻辑。下一步是告诉 devise 使用它而不是默认的。在您的路线中,您有devise_for线路。它应该更改为包括注册控制器。
devise_for :users, :controllers => { :registrations => 'registrations' }
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 use registration_path(:user), :method => :delete— that's where it links. To destroyaction of registrations controller.
下一步是覆盖destroy注册控制器中的操作。当您使用时registration_path(:user), :method => :delete- 这就是它链接的地方。要destroy注册控制器的作用。
Currently devise does the following.
目前设计执行以下操作。
def destroy
resource.destroy
set_flash_message :notice, :destroyed
sign_out_and_redirect(self.resource)
end
We can instead use this code. First let's add new method to Usermodel.
我们可以改为使用此代码。首先让我们向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
Now you should be all set. Use scopes to filter out deleted users.
现在你应该准备好了。使用范围过滤已删除的用户。
回答by Peyman
Adding onto hakunin's answer:
添加到hakunin 的回答中:
To prevent "soft deleted" users from signing in, override active_for_authentication?on your Usermodel:
要防止“软删除”用户登录,请覆盖active_for_authentication?您的User模型:
def active_for_authentication?
super && !deleted_at
end
回答by rausch
You could use acts_as_paranoidfor your User model, which sets a deleted_at instead of deleting the object.
您可以为您的用户模型使用acts_as_paranoid,它设置一个deleted_at 而不是删除对象。
回答by csi
A complete tutorial can be found at Soft Delete a Devise User Accounton the Devise wiki page.
可以在设计 wiki 页面上的软删除设计用户帐户中找到完整的教程。
Summary:
1. Add a "deleted_at" DATETIME column
2. Override users/registrations#destroy in your routes
3. Override users/registrations#destroy in the registrations controller
4. Update user model with a soft_delete & check if user is active on authentication
5. Add a custom delete message
总结:
1. 添加“deleted_at” DATETIME 列
2. 在您的路线中
覆盖 users/registrations#destroy 3. 在注册控制器中覆盖 users/registrations#destroy
4. 使用 soft_delete 更新用户模型并检查用户是否在身份验证中处于活动状态
5.添加自定义删除消息

