ご無沙汰しています。ちけんです。
Railsのユーザー認証に使われるDeviseというGemがあります。
GitHub - plataformatec/devise: Flexible authentication solution for Rails with Warden.
ジェネレータで作られる登録フォームは"email"と"password"と"password confirm"しか作られません。
この記事では、登録フォームをカスタマイズして独自の項目を保存できるようにする方法を紹介します。
なぜしようと思ったか
そもそもDeviseのジェネレータで作られる登録フォームは最小限です。
例えばTwitterの登録画面と比較してみると、結構違うことがわかります。
私たちはTwitterの登録画面を作りたいわけではないですが、しかし、しばしばユーザーの名前を追加したかったり、電話番号を追加したかったりします。
僕がDeviseで作ったUserモデルに名前と電話番号を追加するのに、どうしたのかを書いていこうと思います。
Railsアプリケーションを作る
サンプルとなるRailsアプリケーションを作ります。
ここでは例としてhogefugapiyoアプリケーションというのを作って解説しようと思います。
ちなみにバージョンは下記のとおり
Rails 4.2.6
Devise 4.0.1
rails new hogefugapiyo
cd hogefugapiyo
# Gemfileにdeviseを追加
echo "\ngem 'devise'" >> Gemfile
bundle install
bin/rails generate devise:install
# Userモデルを作る
bin/rails generate devise user
カラムを追加する
何はともあれ、名前と電話番号をUserモデルに追加します。
bin/rails generate migration AddNameAndTelToUsers name tel
bin/rake db:migrate
フォームを変更する
Deviseのカスタムビューを生成します。
bin/rails generate devise:views user
すると下記のようなapp/views/users以下にファイルが作られます。
いろいろファイルがありますが、登録フォームはapp/views/users/registrationsの2ファイルです。
名前と電話番号を追加します。
edit.html.erb
gist582ea89584651909f7921c357f96e129
new.html.erb
gistbfe64cf9867b6102a5fb6d6fd0bd84c4
こんなふうになる
保存処理を変更する
保存処理を変更するためにカスタムのコントローラーを作ります。
rails g devise:controllers users
config/routes.rbを修正して登録処理にカスタムのコントローラーを使用するようにします。
gist3ce1e703a0bd6d1fb351fe1bf9623972
app/controllers/users/registrations_controller.rbを編集します。
registrations_controller.rb
gistf2478670bf287af9fd640add0db5ca08
registrations_controller.rbの解説
ポイントとなるのは以下の部分
before_action :configure_sign_up_params, only: [:create]
before_action :configure_account_update_params, only: [:update]
(中略)
# If you have extra params to permit, append them to the sanitizer.
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
end
# If you have extra params to permit, append them to the sanitizer.
def configure_account_update_params
devise_parameter_sanitizer.permit(:account_update, keys: [:name])
end
ここで新たにフォームに追加したnameを追加しています。
def build_resource(hash=nil)
super(hash)
if params['tel'].present?
first_number = params['tel']['first']
center_number = params['tel']['center']
last_number = params['tel']['last']
end
self.resource.tel = "#{first_number}-#{center_number}-#{last_number}"
end
def update_resource(resource, params)
super(resource, params)
if params['tel'].present?
first_number = params['tel']['first']
center_number = params['tel']['center']
last_number = params['tel']['last']
end
self.resource.tel = "#{first_number}-#{center_number}-#{last_number}"
end
この部分でtelを設定しています。
ストロングパラメーターを使わずに値を設定したいのでこのようにしています。
親クラス(Devise::RegistrationsController)のメソッドを上書きして、こんなような処理を実現するようにしています。
おわりに
僕はこんなふうにしましたが、もっと良いやり方があれば教えてほしいので、だれか記事にしてください。
registration_controller.rbのbuild_resourceとupdate_resourceを上書きしていますが、デフォルトのコメントに入ってなかったのであんまりいいやり方ではないのかもしれません。