ユーザーが意図的にパスワードを変更していないケースで、パスワード変更完了メールが送られると変なので、その処理の時だけ送らないようにしました。
結論は、Device側で用意されてたので、1行追加だけ。skip_password_change_notification!

Deviceの挙動

config/initializers/devise.rb で下記のようにtrueにすると、Deviceと関係ない所、パスワード変更してもメールが送られちゃいます。
after_updateでsend_password_change_notificationメソッドが呼び出されている為。

  config.send_password_change_notification = true

ボツ案:skip_callbackを使う

保存処理の前に下記を追加。
確かに送られなくなるけど、他の所でも送られなくなる。

  User.skip_callback(:update, :after, :send_password_change_notification)

保存処理の後に下記も追加。
何故か、違うユーザーに送られたような。。。
そもそも、並列で送信したい処理が走ったらどうなるんだろう。
危うさを感じるし、魔改造な気がしたので、別の方法を探す。

  User.set_callback(:update, :after, :send_password_change_notification)

解決:フラグを発見

ググったりもするけど、最終的にはソースを読んでいる事が多い。挙動の理解もソースから。

~/.rvm/gems/ruby-3.0.0/gems/devise-4.7.3/lib/devise/models/database_authenticatable.rb

  after_update :send_password_change_notification, if: :send_password_change_notification?

send_password_change_notification?って何してる?

      if Devise.activerecord51?
        def send_password_change_notification?
          self.class.send_password_change_notification && saved_change_to_encrypted_password? && !@skip_password_change_notification
        end
      else
        def send_password_change_notification?
          self.class.send_password_change_notification && encrypted_password_changed? && !@skip_password_change_notification
        end
      end

@skip_password_change_notificationってもしかして。

      def skip_password_change_notification!
        @skip_password_change_notification = true
      end

これが呼べれば良いので、saveする前に呼び出してみる。

  @user.skip_password_change_notification!
  @user.save!

行けました。流石、Device。ちゃんと用意してくれてますね。
callback外すのとは違って、このモデルの値だけが対象なので、他に影響もでない。

今回のコミット内容
https://dev.azure.com/nightonly/rails-app-origin/_git/rails-app-origin/commit/df662f7c0e2bc18423137e138aa1bf6c84e83349?path=%2Fapp%2Fcontrollers%2Fregistration_controller.rb

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です