web-dev-qa-db-ja.com

Deviseでユーザーを「ソフト削除」する方法

現在、Railsプロジェクトでのユーザー登録/認証にDeviseを使用しています。ユーザーがアカウントをキャンセルしたい場合、ユーザーオブジェクトは破棄され、アプリケーションが望ましくない状態になります。

「ソフト削除」を実装する最も簡単な方法は何ですか?つまり、個人データのみを削除し、ユーザーを削除済みとしてマークするだけですか?私はまだすべてのレコードの関連付けを保持したいです。

まず、ユーザーに新しい「削除済み」列を導入する必要があると思います。しかし、その後、ユーザーのプロファイルビューでこのデフォルトコードを使用します。

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

:deleteメソッドはどこにありますか?デフォルトのDeviseメソッドをどのように上書きする必要がありますか?

67
slhck

Userモデルでdestroyメソッドをオーバーライドして、実際に破壊する代わりにupdate_attribute(:deleted_at, Time.current)を実行することをお勧めしますが、標準APIからのこの逸脱は将来負担になる可能性があるため、ここで変更する方法を示しますコントローラー。

Deviseには、すぐに使えるデフォルトのコントローラーがたくさんあります。それらをカスタマイズする最良の方法は、対応するdeviseコントローラーを継承する独自のコントローラーを作成することです。この場合、私たちは_Devise::RegistrationsController_について話します—これはソースを見ることで簡単に認識されます。そのため、新しいコントローラーを作成します。

_class RegistrationsController < Devise::RegistrationsController
end
_

これで、デバイスが提供するすべてのロジックを完全に継承する独自のコントローラーができました。次のステップでは、デバイスにデフォルトの代わりにそれを使用するように指示します。ルートには_devise_for_行があります。登録コントローラーを含めるように変更する必要があります。

_devise_for :users, :controllers => { :registrations => 'registrations' } 
_

これは奇妙に思えますが、デフォルトでは単に「登録」ではなく「開発/登録」であるため、理にかなっています。

次のステップは、登録コントローラーのdestroyアクションをオーバーライドすることです。 registration_path(:user), :method => :deleteを使用すると、そこにリンクします。登録コントローラーの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
_

これで準備は完了です。スコープを使用して、削除されたユーザーを除外します。

103
Max Chernyak

hakunin's answer に追加する:

「ソフト削除」されたユーザーがサインインできないようにするには、active_for_authentication?Userモデル:

def active_for_authentication?
  super && !deleted_at
end
90
Peyman

Userモデルには acts_as_paranoid を使用できます。これは、オブジェクトを削除する代わりにdeleted_atを設定します。

10
rausch

完全なチュートリアルは、Devise Wikiページの Soft Delete a Devise User Account にあります。

概要:
1。 「deleted_at」DATETIME列を追加します
2。ルートでユーザー/登録を上書きする#destroy
3。登録コントローラーでusers/registrations#destroyをオーバーライドします
4。 soft_deleteを使用してユーザーモデルを更新し、ユーザーが認証でアクティブかどうかを確認します
5。カスタム削除メッセージを追加する

6
csi