2011-02-28 41 views
66

我目前在Rails項目中使用Devise進行用戶註冊/身份驗證。當用戶想要取消他們的賬戶時,用戶對象被銷燬,這使我的應用程序處於不希望的狀態。如何用Devise「軟刪除」用戶

什麼是實施「軟刪除」的最簡單方法,即只刪除個人數據並將用戶標記爲已刪除?我仍然想保留所有的記錄關聯。

我假設我將不得不首先爲用戶引入一個新的「已刪除」列。但後來我堅持在用戶的個人資料查看此默認代碼:

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

我在哪裏可以找到:delete方法?我應該如何覆蓋默認的Devise方法?

+0

刪除用戶時應該發生什麼?他的所有帖子/活動是否應該被刪除? – khelll 2011-02-28 10:25:03

+0

我想保留與其他對象的所有關聯,但只刪除個人數據(名稱/電子郵件地址)並禁用登錄。 – slhck 2011-02-28 10:34:00

回答

102

我可以建議覆蓋您的用戶模型中的destroy方法,以簡單地執行update_attribute(:deleted_at, Time.current)(而不是實際銷燬),但這種與標準API的偏差可能在未來變得繁重,因此以下是如何修改控制器。

Devise擁有一堆開箱即用的默認控制器。定製它們的最好方法是創建自己的控制器,繼承相應的設計控制器。在這種情況下,我們正在談論Devise::RegistrationsController - 這很容易通過查看源代碼來識別。所以創建一個新的控制器。

class RegistrationsController < Devise::RegistrationsController 
end 

現在我們有我們自己的控制器完全繼承所有設計提供的邏輯。下一步是告訴設計使用它而不是默認的。在你的路線中,你有devise_for行。應該更改爲包含註冊控制器。

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

這似乎很奇怪,但它很有意義,因爲默認情況下它是'設計/註冊',而不僅僅是'註冊'。

下一步是重寫註冊控制器中的destroy操作。當您使用registration_path(:user), :method => :delete - 這是它鏈接的地方。到destroy註冊控制器的行動。

目前設計做到以下幾點。

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 

現在你應該全部設置。使用範圍來過濾已刪除的用戶。

+0

謝謝對於答案,我已經能夠用你的輸入做出我自己的解決方案! – slhck 2011-02-28 12:11:52

+1

非常感謝您的答覆!請修正錯字:** update_attribtue ** – kravc 2012-02-22 13:28:00

+2

如何讓用戶稍後使用同一封電子郵件重新註冊? – 2013-05-04 19:09:21

10

您可以使用acts_as_paranoid作爲您的用戶模型,該模型設置deleted_at而不是刪除對象。

+0

我以前聽過那個。它如何與Devise進行互動?除了安裝'acts_as_paranoid'之外,我需要改變什麼? – slhck 2011-02-28 10:35:05

+0

@shick ...您應該將'acts_as_paranoid'行添加到您的用戶模型(或任何其他需要軟刪除的模型)。 – rubyprince 2011-02-28 11:05:46

+1

這個寶石有很多的分支/版本,我找不到一個適用於Rails 3.2.x的工具。 – 2012-12-10 14:38:39

89

添加到hakunin's answer

爲了防止「軟刪除」用戶登錄,覆蓋active_for_authentication?User型號:

def active_for_authentication? 
    super && !deleted_at 
end 
+3

+1從當前會話中刪除新刪除的用戶的正確鉤子。 – 2011-11-23 17:45:28

+2

這真的是最好的答案。 [這裏是文檔](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Authenticatable)。 – 2012-12-10 19:29:40

+6

感謝您的支持,我唯一不喜歡的部分是與未確認帳戶共享的消息。看到我的答案如何更改該消息:http://stackoverflow.com/a/14966003/637094 – Leito 2013-02-19 19:47:58

6

一個完整的教程可以在Soft Delete a Devise User Account的設計wiki頁面上找到。

摘要:
1.添加 「deleted_at」 DATETIME列
2.覆蓋用戶/註冊#摧毀你的路由
3.覆蓋用戶/註冊#消滅在註冊控制器
4.更新用戶帶soft_delete的型號&檢查用戶是否在認證時處於活動狀態
5.添加自定義刪除消息