タイトルがいまいち意味不明ですが、下記のやりたいことを実装する上で調べたことが非常に勉強になったので記録しておきます。
#前提条件
・認証にdeviseを使用。googleなどの外部サービスのログインも実装している
#やりたいこと
①通常のemail、passwordでログインした場合、ユーザー情報を変更する(edit_user_registration_path)
時にパスワード変更フォームを表示。情報変更の際に現在のパスワードの入力を要求するように設定。
②外部サービスログインを使った場合は(edit_user_registration_path)
でパスワード変更フォーム、現在のパスワード入力欄を非表示。情報変更の際に現在のパスワード入力も不要な設定にする。
こういった挙動を実装したい。
#実装
①ログイン認証の方式によって、Viewの表示を変更する。
<%if current_user.uid == nil %>
<div class="field">
<%= f.label :password %> <br />
<%= f.password_field :password, autocomplete: "new-password" , class: "form-control form-control-comment" %>
<% if @minimum_password_length %>
<br />
<em><%= @minimum_password_length %> characters minimum</em>
<% end %>
</div>
<p class="comment">(変更したくない場合は空白のままにしてください)</p>
<div class="field">
<%= f.label :current_password %> <br />
<%= f.password_field :current_password, autocomplete: "current-password", class: "form-control form-control-comment" %>
</div>
<p class="comment">(変更するには現在のパスワード入力が必要です)</p>
<% end %>
通常のメールアドレスとパスワードのログインの場合はプロバイダから返ってくる、uid
はnilになっている。
それをif文でViewの表示を分岐させた。
②ユーザー情報を更新する時にパスワード要否を分岐させる
deviseの初期設定ではユーザー情報を更新する時は現在のパスワード入力を求められる。
class Users::RegistrationsController < Devise::RegistrationsController
.
.
.
protected
def update_resource(resource, params)
if current_user.uid == nil
resource.update_with_password(params)
else
resource.update_without_password(params)
end
end
end
どういうことだろう?
```rails g```で自作した```Users::RegistrationsController```は```Devise::RegistrationsController```を継承している。情報を更新する時の仕組みは
Devise::RegistrationsController
のupdateメソッドを読んでいる。
色々辿っていくと、
def update_resource(resource, params)
resource.update_with_password(params)
end
このupdate_with_password
メソッドにつながる。
require 'devise/strategies/database_authenticatable'
module Devise
module Models
.
.
.
def update_with_password(params, *options)
...
current_password = params.delete(:current_password)
if params[:password].blank?
params.delete(:password)
params.delete(:password_confirmation) if params[:password_confirmation].blank?
end
result = if valid_password?(current_password)
update(params, *options)
else
assign_attributes(params, *options)
valid?
errors.add(:current_password, current_password.blank? ? :blank : :invalid)
false
end
.
.
.
end
end
このメソッドは現在のパスワードが入力されていない、もしくは間違っている場合は情報を更新しないようになっている。
このupdate_with_password
と同じところにupdate_without_password
メソッドもある。
これこそがパスワードなしで情報を変更できるメソッド。
仕組みがわかればUsers::RegistrationsController
でupdate_resource
メソッドを上書きする。
やりたいことはViewと同じであり、現在のユーザーがプロバイダから返ってくるuidを保持しているかnilかで発火させるメソッドを分岐させた。
#学び
ググれば色んな方が情報発信してくれているが、一次情報を見る癖もつけないといけない
#参考
https://github.com/heartcombo/devise/tree/769506e96cd45b36a311eeca293ce0228c58e5f3