箱のプログラミング日記。

渋谷の自社開発企業でRails書いてます。

Ralisで入力確認用フォームを作りたい【_confirmation】

f:id:y_hakoiri:20191120232646j:plain

サービスを作っていると「パスワードやメールアドレスの確認用入力フォームを作りたいな〜」みたいな時ありますよね。

イメージこんな感じ。

f:id:y_hakoiri:20191214112358p:plain

(パスワードだったらユーザー認証のライブラリがだいたいやってくれてるような気もしますが。。)

Rails標準のヘルパーでめちゃくちゃ簡単に実現できます。

今回はユーザーのメールアドレスの確認フォームということを想定して、対象のカラムはemailとします。

やること

  • email_confirmationのフォームを用意する
  • email_confirmationをストロングパラメーターで許可する
  • emailのバリデーションにconfirmation: trueを追加する

これだけ。めちゃ簡単

email_confirmationのフォームを用意

_form.html.slim

= f.text_field :name
= f.text_field :email
= f.text_field :email_confirmation

ストロングパラメーターで許可

users_controller.rb

class UsersController < ApplicationController
 ・
 ・
 ・
 private
 def user_params
  params_require(:user).parmit(:id, :name, :email, :email_confirmation)
 end
end

(わかりやすくするためにだいぶ割愛)

まあここまでは普通というか特につまづくところもないのですが、モデルのバリデーション周りでちょっと頭を使った。

confirmation: trueを追加

models/user.rb

validates :email, presence: true, email_format: true, uniqueness: true, confirmation: true

で、リファレンスにこう書いてあるんだけどさ。。

2つのテキストフィールドで受け取る内容が完全に一致する必要がある場合に使います。

このチェックは、email_confirmationがnilでない場合のみ行われます。確認を必須にするには、確認用の属性について存在チェックも追加してください。

確認欄に何も入力しないと、nilじゃなくて「""」がパラメーターで渡されるから、email_confirmationを必須入力にしなくても、この状態だと結局毎回必ず完全一致のチェックが効いてしまうんですよ。まあ、そうしないとブランクおっけーになっちゃうもんね。

私の場合、特定のケースのみ完全一致のチェックをすっ飛ばしたかったので、ここでちょっと悩んだ。

解決

confirmation: trueだけ切り分けてwith_optionで呼び出すことで成功。

models/user.rb

validates :email, presence: true, email_format: true, uniqueness: true

with_options if: hogehoge do
 validates :email, confirmation: true
end

def hogehoge
 return true if name == 'hogehoge'
end

名前がhogeさんのときだけ、確認用メールアドレスの完全一致チェックが入ります。

(実際そのような仕様は存在しないが)

特定の条件下のみでバリデーションを適用させたいときの方法はいくつかあるけど、with_optionsを使うとtrueが返ってきたときだけバリデーションを実行してくれて、かつ条件部分を別メソッドに切り分けたりもできるので結構便利。

まとめ

  • 確認入力欄を作りたいときはname属性をカラム名_confirmationとする
  • バリデーションでconfirmation: trueを追加すると完全一致チェックをしてくれる
  • カラム名_confirmationに渡ってきた値がnilの場合は完全一致チェックがされない

余談

メールアドレスの入力欄を2回設ける仕様って普段結構いろんなサービスで目にするけど、昨今2段階認証が当たり前になっているし、2回入力させる意味ってほとんど無いんじゃないかな〜とこれ書いてて思った。。

一生懸命実装したけど、「これってそもそも必要あったの?」「ここにこれだけの工数割くのって有益だった?」って後から思うことってよくありますよね。。

技術力が追いついてくると、こういうのも実装する前に気がつけるようになるんだろうな...!

参考

Active Record バリデーション - Railsガイド