らくだ🐫にもできるRailsチュートリアル|番外編・パスワードのバリデーション

番外編では本編からちょっと外れた話なんかを書いていきます

パスワードのバリデーションをアレンジする

チュートリアル本編でUserモデルのバリデーションの話が出てきました
せっかく(?)なので、パスワードのバリデーションをアレンジしていこうと思います

本文では「最小6文字」だけだったけど
「最大13文字」→「英・数・記号を各1文字以上」→「英大文字・英小文字・数・記号を各1文字以上」
こんな感じにステップアップ(?)していきます

現在の状態

パスワードのバリデーション (パスワードが)存在する ,長さ 最小6文字

最大12文字

実際は100文字とか、もっと多い設定でいいっぽいんだけど
ひとまず最大値を12文字としてみます。

テスト

バリデーション

コンソールで色々試して、
13文字以上のパスワードを設定するとちゃんとfalseになりました

英・数・記号を各1文字以上

まずは厄介そうな正規表現の組み立てから

Rubular
上記のサイトで色々試しながらやっていきます
a~zから一文字 → a-z
数字一文字 → \d
記号を一文字 → \D
\Dは英字と記号両方(数字以外)なので \Wに
\W → 単語以外の文字 (\wで表現される任意の単語文字(文字、数字、アンダースコア)以外の文字)

これを組み合わせて
[a-z\d\W] ←これだとどれか1個が入っていればOKになっちゃうからアウト
[a-z]\d\W ←これだと各1文字以上はクリアするけど順不同にできない

わかる範囲の事を色々試すも上手くいかないのでググりまして
こちらを参考に組み立てられそうな気持になるものの


書かれている内容がどういうことなのか良くわからない
Slackで悩んでいると参考ページを教えていただけましたアリガタヤ

そして、これで良さそうかな?という正規表現が出来ました
\A(?=.*?[a-z])(?=.*?\d)(?=.*?\W)[!-~]+\z
(?=.*?[a-z]) → 「任意の0回以上の文字列(文字があってもなくてもいい)とa-zのうちの一文字」が条件
(?=.*?\d) → 「任意の0回以上の文字列(文字があってもなくてもいい)と数字のうちの一文字」が条件
(?=.*?\W) → 「任意の0回以上の文字列(文字があってもなくてもいい)と文字、数字、アンダースコア以外の文字のうちの一文字」が条件
[!-~]+ →ASCIIコードの順番の!-~のうちのいずれかを一文字以上繰り返す
「○○を一文字以上」の条件を指定する表現と、使う文字の指定の表現

使う文字の指定が「.(任意の文字)」じゃダメなのは空白を含んじゃうからかな?

と言う訳で
/\A(?=.*?[a-z])(?=.*?\d)(?=.*?\W)[!-~]+\z/i
これで試してみることにしました(因みにこのままではまだ間違ってるw)

テスト

emailの部分を参考に@user.password= @user.password_confirmationが
trueの時に成功するテストとfalseの時に成功するテストを書く

因みにこのままでは問題が残っています🐫

バリデーション

テスト

ここでテストは赤に

特に注目したのが上記ハイライト部分
コードの該当部分は下記

@userがtrueの時に成功するテストが失敗しているんですね

ん?@user?
って事でsetupメソッドの中のオブジェクトに注目してみる
パスワードが正しい形になっていませんね?!
と言う事で該当箇所を修正

無事、テストが通るようになりました✨🐫

コンソールで試してみる

念の為(?)コンソールでいくつか試してみたところ
タイポしてないのにfalseが返ってきました

パスワードがダメっぽい?
記号は「_(アンダーバー)」使ってるのに🐫?

・・・・・・!
らくだ🐫は思い出しました!
\W → 単語以外の文字 (\wで表現される任意の単語文字(文字、数字、アンダースコア)以外の文字)
\Wには「_」が含まれていないと言う事に!!
なので正規表現の該当部分を修正

エラーにはならない問題点

さて、ここで気づいたんだけどエディタのuser_test.rbに⚠マークが

テストではエラー出てないのに🤔となりつつ
ポインターを合わせるとメッセージが出たのでググってみました

こちらでずばり


配列を代入した変数名とブロックパラメータが同じなのは良くないと言う事ですね
emailの方を見直して見ると確かに別々になっていました
なのでサクッと修正します

これで英・数・記号を各1文字以上の検証を追加することが出来ました✨
→そもそも規約に合わせて配列の変数名は複数形にしよう!ですよ!

因みに、
ここでは英字の小文字と大文字を区別しないので
正規表現の末尾に「i」を付けています。
なので、validationも「before_save { email.downcase!, password.downcase! }」と付けたほうがいいのかもでした。
小文字に変換してからvalidationにかけられる様に「before_save { email.downcase!, password.downcase! }」と付けたほうがいいのかもでした。
→本文に倣っての「before_save」でしたが、タイミング的にこれでは遅いっぽい?


→やるならbefore_validationが適切っぽい
→でも入力された数値を勝手に変換するのはよくなくない?
→なので「大文字小文字の区別はされません」などの注意書きがあった方が良い感じ

英大文字・英小文字・数・記号を各1文字以上

上記が出来ていれば後は簡単アレンジ🐫

正規表現

/\A(?=.*?[a-z])(?=.*?[A-Z])(?=.*?\d)(?=.*?[\W_])[!-~]+\z/
英小文字と英大文字をそれぞれ別々に条件設定
末尾に「i」(大文字と小文字を区別させないオプション)は付けない

テスト

setupメソッド内のpassword部分を英大文字・英小文字・数字・記号それぞれを含むように修正
また、上記で追加したテストも該当部分を修正

バリデーション

正規表現部分を英大文字と英小文字が区別される様に差し替え

テスト

テストもGREEN
サンドボックスなコンソールで色々試した結果も希望通りの物でした🎵🐫

まとめとか感想

参加しているコミュニティ
パスワードのバリデーションに最大文字数も設定してみようと呟いたところ
「英数字記号1文字以上必須にしよう!」
「英字は大文字小文字それぞれにしちゃう?」
と、ハードルを丁度良く上げていただいたことがきっかけでとても勉強になりました🐫

詰まった時にヒントをもらえたりは勿論なんだけど
そもそも一人だったらこのタイミングでここまで挑戦しなかっただろうなって。
なので、とても感謝しておりますのだ。

他にもemailと部分一致は不可にするとかもあったんだけど
とりあえずパスワードのバリデーションのアレンジ」はひと段落としますw(いずれ挑戦したいです)

次からRailsチュートリアルの7章に入りますー