Deviseで生成したユーザーの更新フォームに自前のフィールドを追加する
移転しました →
Rails4+Deviseの話。Deviseでユーザーを作るとデフォルトでユーザー情報更新フォームがついてくる。これはbootstrapでスタイル付けしてあるものだけど、基本はこんな感じになる。
このUserモデルに対して別のフィールドをいくつか追加した上で、同じフォームで更新可能にするにはどうしたらいいのか、というのが今日のテーマ。
例えば名前とか、表示名とか、住所とか、そういう情報がアプリケーションに依っては必要になってくると思う。
今回はnameというカラムをUserに持たせることにする。なお、add_column :users, :name, :string
みたいなマイグレーションは既に済んでいるとする。
DeviseのカスタムViewを用意する
% rails generate devise:views
このコマンドによってアプリケーションディレクトリ内にdevise用のビューが生成される。ちなみに先ほどのスクリーンショットは生成したビューを日本語化したもの。
これをやっておくことでDeviseのコントローラが表示に使うビューを自由に変更することができる。
registrations/edit.html.hamlを編集する
erbの人は随時読み替えてもらえばOK。app/views/devise/registrations/edit.html.haml
にname
用のフィールドを追加する。
例えばこんな感じで3行ほど追加する。
%h2 アカウント情報更新 = form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put, role:"form" }) do |f| = devise_error_messages! -# この3行を追加 ################################################## .form-group = f.label :name, "名前" = f.text_field :name, :autofocus => true, class:"form-control" -# ############################################################## .form-group = f.label :email, "Eメール" = f.email_field :email, class:"form-control" - if devise_mapping.confirmable? && resource.pending_reconfirmation? .form-control Currently waiting confirmation for: #{resource.unconfirmed_email} .form-group = f.label :password, "パスワード" %i (パスワードを変更しない場合は空欄のままにしてください) = f.password_field :password, :autocomplete => "off", class:"form-control" .form-group = f.label :password_confirmation, "パスワード(再入力)" = f.password_field :password_confirmation, class:"form-control" .form-group = f.label :current_password, "現在のパスワード" %i (更新するために現在のパスワードが必要です。) = f.password_field :current_password, class:"form-control" .form-group = f.submit "更新", class:"btn btn-primary" %h3 退会 %p 退会してユーザー情報を削除しますか? #{button_to "退会する", registration_path(resource_name), :data => { :confirm => "よろしいですか?" }, :method => :delete, class:"btn btn-danger"} = link_to "戻る", :back
さあこれでフォームができたからもう動くだろうと思ってみると実際にはそうはいかない。Rails4から導入されているStrong Parametersの概念により、許可されていないname
を更新できないというエラーが発生してしまうからだ。
Devise用のコントローラを作る
name
の更新を許可するため、Deviseのコントローラを継承したものを用意する必要がある。このコントローラでは、更新のためのupdate
アクションでのみname
パラメータを追加でpermit
するという処理を行い、それ以外はベースクラスであるDevise::RegistrationsController
でDevise従来の処理を行う。
# app/controllers/users/registrations_constroller.rb class Users::RegistrationsController < Devise::RegistrationsController before_action :configure_permitted_parameters, only: [:update] private def configure_permitted_parameters devise_parameter_sanitizer.for(:account_update) do |u| u.permit(:name, :email, :password, :password_confirmation, :current_password) end end end
パラメータの許可はdevise_parameter_sanitizer
というDevise用のオブジェクトを経由して行われていて、この部分で:name
も許可対象として指定してあげれば良い。
そしてconfig/routes.rb
を編集し、新しく作ったUsers::RegistrationsController
を使うようにルートを書き換えればよい。
# before devise_for :users # after devise_for :users, controllers: { registrations: 'users/registrations' }
完成!