今回達成すること
前回作成したユーザーテーブルにバリデーションを設定していきます。
全体のバリデーション設定は以下のようになります。
カラム | 内容 | 入力 | 最小文字数 | 最大文字数 | 書式チェック | 一意性 |
---|---|---|---|---|---|---|
name | ユーザー名 | 必須 | 30 | しない | なし | |
メースアドレス | 必須 | 255 | する | なし | ||
password_digest | パスワード | 必須 | 8 | 72(bcryptの仕様) | する | なし |
activated | メール認証フラグ | - | - | - | - | |
admin | 管理者フラグ | - | - | - | - |
今回はname
とpassword
のバリデーション設定を行い、email
は次の記事でカスタムバリデーションを設定します。
それでは参りましょうー。
パスワード暗号化のメソッドを追加
バリデーション前にパスワードを暗号化するメソッドを追加しましょう。
「app/models」ディレクトリのhas_secure_password(ハズセキュアパスワード)
メソッドを追加します。
api/app/models/user.rb
class User < ApplicationRecord
# 追加
# gem bcrypt
has_secure_password
end
has_secure_passwordとは?
has_secure_password
とは、Gem bcrypt(ビークリプト)
を追加すると使えるようになるメソッドで、パスワードを暗号化して保存してくれます。
使い方は簡単で、モデルファイルにhas_secure_password
を追加するだけ有効になります。
注意点は、暗号化されたパスワードはpassword_digest
というカラムに保存されるので、同一名称のカラムを用意しておく必要があります。
has_secure_passwordの便利機能
このメソッドを追加するだけで様々な便利機能が使えます。
passwordとpassword_confirmation属性の追加
-
ユーザーテーブルへ保存する際に
password
属性で保存が行えます。これにより、正式なカラム名
password_digest
属性を使用する必要がなくなります。 -
password_confirmation(パスワードコンファーメイション)
とは、データベースに保存されない仮想の属性で、パスワードの入力確認に使われます。この属性を使用すると
password
とpassword_confirmation
の双方が一致しているかのバリデーションが自動で追加されます。
authenticate()メソッドの追加
authenticate()
とは、ユーザーのパスワード一致判定を行うメソッドです。
このメソッドを使えば、ユーザーが正しいパスワードを入力しているかを判定することができます。
引数にそのユーザーのパスワードを渡し、一致すればユーザーを返し、不一致の場合はfalseを返します。
> User.first.authenticate("password")
パスワードの最大文字数が72文字になる
自動で最大文字数72文字のバリデーションが追加されます。
自身でバリデーションを設定した場合は、エラーメッセージが2重で表示されます。
最大文字数制限のバリデーションは追加しないようにしましょう。
ユーザー作成時にパスワードの入力を検証してくれる
新規会員登録の時だけ入力必須を検証してくれるバリデーションが追加されます。
更新時には検証されません。
これにより、パスワード更新のバリデーションがより簡単に行えます。
nameのバリデーション
それではバリデーション設定に入ります。
name
のバリデーションを追加しましょう。
api/app/models/user.rb
class User < ApplicationRecord
...
# 追加
# validates
validates :name, presence: true,
length: { maximum: 30, allow_blank: true }
end
presence(プレゼンス): true
... 入力必須を検証します。length: {}
... 文字数について検証します。maximum(マキシマム): 30
... 文字数30文字までを検証します。allow_blank: true
... NULL、空白の場合は検証をスキップします。
allow_blank: trueの使い所
例えば「入力必須」と「文字数10文字以上」のバリデーションを設定したname
カラムを未入力で保存した場合。
Railsは素直なので双方の検証エラーを吐き出します。
「名前を入力してください」
「名前は10文字以上で入力してください」
エンドユーザーからすれば、エラーメッセージが大量に表示されることは非常にストレスです。
ここで出力すべきは入力してないことによるエラー「名前を入力してください」のメッセージだけで良いのです。
このようにallow_blank: true
は、未入力の場合に無駄な検証を行わない場合に使用します。
passwordのバリデーション
続いてパスワードのバリデーション設定を行います。
api/app/models/user.rb
class User < ApplicationRecord
...
# 追加
VALID_PASSWORD_REGEX = /\A[\w\-]+\z/
validates :password, presence: true,
length: { minimum: 8 },
format: {
with: VALID_PASSWORD_REGEX
},
allow_nil: true
end
2021年02月17日
allow_blank
の場合、空白文字のパスワードアップデートを許容するため、allow_nil
に変更しました。重大なバグがあるコードを記載していたことをお詫びいたします。
-
length: { minimum: 8 }
... 8文字以上であるかを検証します。 -
format: {}
... 入力形式を検証します。with: VALID_PASSWORD_REGEX
... 入力形式を変数で指定しています。
-
VALID_PASSWORD_REGEX = /\A[\w\-]+\z/
... 正規表現で入力形式を宣言しています。\A
... 文字列の先頭にマッチ[\w\-]
... 「a-zA-Z0-9_」と「-」にマッチ+
... 一回以上繰り返す\z
... 文字列の末尾にマッチ- まとめ ... 先頭から末尾まで、全て「a-zA-Z0-9_」と「-」にマッチする文字列を許容する。
-
allow_nil: true
... 空パスワードのアップデートを許容する。ユーザー編集画面ではセキュリティ上、パスワードを表示しません。
その場合、空白でもバリデーションが通るようこの設定を行います。
ユーザー新規作成時には、
has_secure_password
メソッドが入力必須を検証してくれるので安心してください。
activated, adminのバリデーション
今回、activated
とadmin
に対するバリデーションは行いません。
Boolean型に入力必須の検証はできない
まず、Boolean型に対するバリデーションにpresence: true
(入力必須)は正常に動作しません。
# NG
validates :activated, presence: true
値がfalse
の場合にRailsがバリデーションエラーを返してしまうからです。
Boolean型に入力必須のバリデーションは設定しないようにしてください。
対応)入力値を検証するinclusionを使う
Boolean型に正しくtrue
、false
が入っているかを検証するにはinclusion(インクルージョン)
を使います。
# OK
validates :activated, inclusion: { in: [ true, false ] }
inclusion: { in: [引数] }
... ユーザーが入力した値が引数に含まれているかを検証します。
今回の場合)バリデーションの設定はしない
今回の場合は、マイグレーションファイルでデフォルト値(false
)を設定しています。
意図的にNULLを保存しない限り、NULL値が保存されることはありません。
さらにRailsはtrue
、false
以外の値が入力された場合Boolean型に変換して保存を行います。
つまり、NULLになるリスクもBoolean型以外の値が保存されるリスクもかなり低いということです。
そこにバリデーションは必要ないと判断し設定していません。
(今回はここまで。)
まとめ
この記事ではユーザーモデルにname
とpassword
のバリデーションを設定しました。
筆者も最初はBoolean型のカラムにせっせとバリデーションを設定していたのですが、何度も書いてて「あ、いらんなこれ」と気付きました。
ガチガチのバリーデーションよりも、ユーザーが操作するUI画面をちゃんと設計することの方が大切です。
さて次回は?
バリデーションのエラーメッセージを日本語化に対応する設定を行います。
Railsには多言語化対応する「I18n(アイエイティーンエヌ)」モジュールはデフォルトで入っています。
次回はその「I18n」モジュールが読み込む日本語用ファイル、
↓下の記事リストに続く。
修正情報
-
2021年02月17日
パスワードバリデーションのコードを修正しました。