Devise.4 パスワードなしでユーザー情報を更新
Devise.3 で作成したregistrations_controller.rbで,ユーザー情報を編集画面(app/views/devise/registrations/edit.html.erb)で更新できるようにしたい。デフォルトの設定だと、ユーザー情報を更新するときにパスワードの入力が必要になるが、パスワードなしでも更新できるように設定する。
4.1 パスワードの解除
次のサイトを参考
easyramble.com
4.1.1 編集のView
app/views/devise/registrations/edit.html.erbから次のcurrent_password のフォーム削除するか、if false で囲み出力させないようにする。
<div class="field"> <%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br /> <%= f.password_field :current_password, autocomplete: "current-password" %> </div>
<!-- 編集 --> <h4 class="text-center"><%= t('.title', resource: resource_name.to_s.humanize) %></h4> <!-- form_for --> <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> <!-- 名前の入力らんを追加 --> <div class="form-group"> <%= f.label :name %> <%= f.text_field :username, autofocus: true, class: "form-control", placeholder: '50字以内'%> </div> <!-- メールアドレス --> <div class="form-group"> <%= f.label :email %> <%= f.email_field :email, autofocus: true, autocomplete: 'email', class: 'form-control' %> </div> <!-- パスワード --> <div class="form-group"> <%= f.label :password %> <%= f.password_field :password, autocomplete: 'new-password', class: 'form-control' %> <small class="form-text text-muted"><%= t('.leave_blank_if_you_don_t_want_to_change_it') %></small> </div> <!-- 確認用パスワード --> <div class="form-group"> <%= f.label :password_confirmation %> <%= f.password_field :password_confirmation, autocomplete: 'new-password', class: 'form-control' %> </div> <div class="form-group"> <%= f.submit t('.update'), class: 'btn btn-primary col-md-12' %> </div> <% end %> <!-- <p><%= t('.unhappy') %>? <%= link_to t('.cancel_my_account'), registration_path(resource_name), data: { confirm: t('.are_you_sure') }, method: :delete %>.</p> --> <%= link_to t('.cancel_my_account'), registration_path(resource_name), data: { confirm: t('.are_you_sure') }, method: :delete %></p> <!-- <%= link_to t('.back'), :back %> --> </div>
ルーティング
ルーティングを次のように変更
devise_for :users, controllers: { registrations: 'users/registrations' }
コントローラ
参考サイトにかいているように、Devise では Devise::RegistrationsController#update の中で、Devise::RegistrationsController#update_resource が呼び出されており、その実装はデフォルトでは以下のようになっている。
def update_resource(resource, params) resource.update_with_password(params) end
なので、カスタマイズしたコントローラー(例えば Users::RegistrationsController < Devise::RegistrationsController)で、以下のようにオーバーライドする。
protected def update_resource(resource, params) resource.update_without_password(params) end
update_without_passwordは Devise で実装されており、パスワードなしで更新を行うメソッド。ただし、これだとパスワード自体を更新できない。なので、update_without_current_passwordとし、
class RegistrationsController < Devise::RegistrationsController protected def update_resource(resource, params) resource.update_without_current_password(params) end end
User モデルに update_without_current_password を実装
def update_without_current_password(params, *options) params.delete(:current_password) if params[:password].blank? && params[:password_confirmation].blank? params.delete(:password) params.delete(:password_confirmation) end result = update_attributes(params, *options) clean_up_passwords result end
4.2 Devise::RegistrationsController#update をオーバーライド
updateアクション
def update self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key) prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email) #if update_resource(resource, account_update_params) if resource.update_without_current_password(account_update_params) yield resource if block_given? if is_flashing_format? flash_key = update_needs_confirmation?(resource, prev_unconfirmed_email) ? :update_needs_confirmation : :updated set_flash_message :notice, flash_key end sign_in resource_name, resource, :bypass => true respond_with resource, :location => after_update_path_for(resource) else clean_up_passwords resource respond_with resource end end end
userテーブルに追加したカラムをStrong Parametersに追加して更新できるようにする。
このままでは、userテーブルに追加したusernameやavatarが更新されないので、つぎのようにする。
protected # If you have extra params to permit, append them to the sanitizer. def configure_account_update_params devise_parameter_sanitizer.permit(:account_update, keys: [:username]) #追加 devise_parameter_sanitizer.permit(:account_update, keys: [:email]) devise_parameter_sanitizer.permit(:account_update, keys: [:attribute]) devise_parameter_sanitizer.permit(:account_update, keys: [:password]) #追加 devise_parameter_sanitizer.permit(:account_update, keys: [:avatar]) #追加 end