Rails勉強ログ#2 バリデーションの設定

今日もがっつりアプリの実装練習をしてきましたので、ログを残していきます。


ユーザーモデルにバリデーションを設定する

やりたいこと

新しく作るサイトで、ユーザー新規登録の操作に対してバリデーションをかけたい。

バリデーションとは?

Webサイトで会員登録をする際に、

  • パスワードは大文字・小文字・英数字を含めてください!

  • 氏名(カナ)は全角カタカナで入力してください!

など出てくるアレ。
要は「受け付ける文字種に縛りを入れる」こと。

コード例

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  with_options presence: true do
    validates :nickname
    validates :name, format: { with: /\A[ぁ-んァ-ヶ一-龥々ー]+\z/, message: "全角ひらがな、全角カタカナ、漢字で入力して下さい" }
    validates :name_katakana, format: { with: /\A[ァ-ヶー-]+\z/, message: "全角カタカナで入力して下さい" }
    validates :birthday
  end

  PASSWORD_REGEX = /\A(?=.*?[a-z])(?=.*?[\d])[a-z\d]+\z/i.freeze
  validates_format_of :password, with: PASSWORD_REGEX, message: 'パスワードには英字と数字の両方を含めてください'
end

解説

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

この部分はdeviseを使ってuserモデルを作ったらデフォルトで入っている各種設定。詳しいことはまだ知らない。

userモデルの各カラムへの設定

  with_options presence: true do
    validates :nickname
        validates :name, format: { with: /\A[ぁ-んァ-ヶ一-龥々ー]+\z/, message: "全角ひらがな、全角カタカナ、漢字で入力して下さい" }
    validates :name_katakana, format: { with: /\A[ァ-ヶー-]+\z/, message: "全角カタカナで入力して下さい" }
  end

まず1行目の、with_options presence:true do~end で囲まれているところは、
「 nickname, name, name_katakana, birthday には必ずデータを入れてね。空白は受け付けないよ」という意味。
全部のカラムに presence: true を書かなくてすむのでコードがコンパクトになる。
ただ、とにかく使えば良い!というわけでもないようで、
Claude3に聞いたところ以下の回答が得られた。

with_optionsを使うメリットは以下のようなことがあげられます。
- 複数のフィールドに対して同じバリデーションを簡潔に記述できる
- 重複するバリデーション設定を避けられる
- コードが読みやすくなる
一方で、with_optionsを使わずに個別にバリデーションを設定することも可能です。
どちらを使うかはコーディングスタイルの好みによるところがあります。
モデルのバリデーションでwith_optionsを活用することで、コードの可読性が向上し、バリデーションのメンテナンス性が良くなります。

Claude3

正規表現による文字種の指定

validates :name, format: { with: /\A[ぁ-んァ-ヶ一-龥々ー]+\z/, message: "全角ひらがな、全角カタカナ、漢字で入力して下さい" }
validates :name_katakana, format: { with: /\A[ァ-ヶー-]+\z/, message: "全角カタカナで入力して下さい" }

ここは「正規表現」という書き方を使って、

  • 「名前にはかな・カナ・漢字が使えます」

  • 「フリガナはカタカナでよろしく」

ということを表現している。
ユーザーが決まりを守らないと message: に定義したエラーメッセージを返す。

正規表現は、「正規表現であること自体を示す枠組みを担う文字」と「正規表現で表される中身の文字」が羅列されるので、一見理解不能な呪文に見える。というか、今でも脳が理解を拒んでいる感はある
まぁ、いざ使うときはググればよいので
「指定したい文字種によって、専用の呪文がある」くらいの認識でも、一応実装はできそう。

パスワードのバリデーション

最近は、パスワードに文字種の制限がかかっているサイトが増えた。
たとえばパスワードの文字種に「英数混合必須」の制限をかける呪文はこちら。freezeをくっつけることで改変を防止している。

PASSWORD_REGEX = /\A(?=.*?[a-z])(?=.*?[\d])[a-z\d]+\z/i.freeze
validates_format_of :password, with: PASSWORD_REGEX, message: 'パスワードには英字と数字の両方を含めてください'

でも、これは上述の通り、「英数混合」の条件しかない。
そして、最低文字数はdevise標準の「6文字以上」
たとえば、6文字のPWは ( 26+10 ) ^ 62,176,782,336通りしか存在せず、すぐに解読されてしまう。たぶん。

もっとつよいパスワードを必須にしてみよう

PASSWORD_REGEX = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/.freeze
validates_format_of :password, with: PASSWORD_REGEX, message: 'パスワードには大文字・小文字・数字・記号をすべて含めて8文字以上にしてください'

どうでしょうか。
8文字以上の英数必須、大文字小文字必須、記号も必須。
これなら( 26 + 26 + 10 + 7 ) ^ 8 = 513,798,370,000,000 パターンぐらい?あるので、まぁ大丈夫でしょう。
(そもそも二要素認証の時代に、PWの強さだけで勝負するのはどうなの?…みたいな話はここでは割愛 というかそもそもパスワードに制限をかけたい、という話でした)

まとめ

  1. バリデーションとは、「文字の種類を限定」したり、「空欄を許可しない」などの設定。

  2. 文字種を制限するには、「正規表現」という手法をつかって許可する文字を指定する。

  3. パスワードの指定には、専用の呪文を使う。

備忘録おわり。

この記事が気に入ったらサポートをしてみませんか?