多分、deviseは結構昔からあるgemだし、皆さんよく知ってるのだろうけど、せっかくなので残してみる。
deviseで対象のモデルに:confirmableを有効にしている(登録や、登録内容を更新する際に。確認メールを利用者に通知する仕組み)場合、emailを更新したいときは基本的に利用者の確認が取れていないと更新できないようにdeviseが制御してくれている。
ただ、たまにこの確認をスキップしてemailを更新をしたいときがあったりする。そういうときはどうするか???
td;lr
skip_reconfirmation!
こういったメソッドがあって、中では確認作業をスルーするかどうかを判定するインスタンス変数@bypass_confirmation_postponeをtrueにしてるだけ。
このメソッドを実行した後なら、emailをupdateすることが可能。再確認作業をスキップできる。
ref: https://github.com/plataformatec/devise/blob/715192a770/lib/devise/models/confirmable.rb#L167-L169
(ちなみに登録時の確認もスキップさせるskip_confirmation!もある。 ref: https://github.com/plataformatec/devise/blob/715192a770/lib/devise/models/confirmable.rb#L155 )
他の方法
update_column(email: 新しいメアド)
emailを更新したいときはupdate_columnとかでSQLを直接実行して更新することもできる。けど、バリデーションを通さないし、updated_atなども更新しないので、その点を注意したほうが良さそう。まあでもこっちのが手軽っちゃあ手軽感はある。
そもそも確認をスキップしたタイミングなんである?
なんで、こんなことを調べたかって言うと、テストを書いているときに「ある処理でメアドを更新して、それが正しく更新されているか」をテストしたかった(Rspec)。
use = User.find(1)
user.assign_attributes(email: "hoge@example.com")
user.save!
こんな感じでbefore句を書いて、expect(user.email).to eq 変更したメアドという感じで、emailが更新されるかをテストしたかったんだけど、通らない。
なんでだろうと思って、user.save!した後メアドが更新されているか見てみると、更新されていない(この辺、save!したときにdeviseさんがwarningやらalert出してくれるとありがたいな〜と思ったけど)。
いろいろ考えて、「そういえばdevise使ってるけど、それのせいかな?」と思い始め、ググって以下の記事を見つけ参考にさせていただいた。
http://docs.komagata.org/5436
確かに更新処理の前にconfig.reconfirmableをfalseにしたら更新できたけど、テストコードにそれを書くのはなんかな〜、、、となり、もうちょいdeviseを調べて「再確認をスキップしてメアドを更新する」みたいなことできないかな〜きっとできるだろ〜と思って調べてて、コードを追ってくのが辛かったので、とりあえずテストコードから漁っていたら関連してるっぽいもの発見。
https://github.com/plataformatec/devise/blob/715192a770/test/models/confirmable_test.rb#L379-L388
'should not regenerate confirmation token or require reconfirmation if skipping reconfirmation after changing email'
「メアド変えて、skipping_reconfirmationしたら、トークン作成と再確認はしない」。それっぽい!中も見てみると、skip_reconfirmation!してる。といった感じで探した。
(ちなみに、最初にテスト通らなかったとき更新されなかったのは、以下のbefore_updateのせいっぽい。 ref: https://github.com/plataformatec/devise/blob/715192a770/lib/devise/models/confirmable.rb#L58
再確認とトークン再作成が済んでなかったらメアド更新は保留にするようにしてるみたい。)