19
23

More than 3 years have passed since last update.

[Rails]パスワードのバリデーションに正規表現を使用してみた[format]

Last updated at Posted at 2020-05-02

はじめに

今回は、正規表現でパスワードのバリデーションをしてみました。
railsではformatというバリデーションヘルパーで正規表現を使用することができます。
求めるパスワードの条件として「半角6~12文字で英大文字・英小文字・数字それぞれ1文字以上含む」でないと登録できないようにしました。
実行結果はRSpecのモデルのテストで確認していきます。

参考にさせていただいた記事等

言語別:パスワード向けの正規表現
パスワード向け正規表現 /^(?=.?[a-z])(?=.?\d)[a-z\d]{8,100}$/i を解読する

前提条件

すでにユーザー作成機能作成を作成済みとします。
私はrailsチュートリアルで作成したログイン機能を使って進めました。
完成したもの先に記載するしておきます。

/app/model/user.rb
VALID_PASSWORD_REGEX =/\A(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[\d])\w{6,12}\z/
  validates :password, presence: true,
            format: { with: VALID_PASSWORD_REGEX,
             message: "は半角6~12文字英大文字・小文字・数字それぞれ1文字以上含む必要があります"}

1.テストを失敗させる

失敗するテストを書く前に現状のpasswordに関するバリデーションを確認します。
現状ではパスワードが空でないこと、長さが6文字以上であることのみのバリデーションとなってます。

ruby/app/model/user.rb
validates :password, presence: true, length: { minimum: 6 }

失敗するテストはこちら。

spec/mpdel/user_spec.rb
  it 'パスワードに英小文字が含まれない場合無効な状態であること' do
    user = User.new(password: '1'+'A' * 5, password_confirmation: '1A'+'a' * 3)
    user.valid?
    expect(user.errors[:password]).to include('は半角6~12文字英大文字・小文字・数字それぞれ1文字以上含む必要があります')
  end

  it 'パスワードに英大文字が含まれない場合無効な状態であること' do
    user = User.new(password: '1'+'a' * 5, password_confirmation: '1A'+'a' * 3)
    user.valid?
    expect(user.errors[:password]).to include('は半角6~12文字英大文字・小文字・数字それぞれ1文字以上含む必要があります')
  end

  it 'パスワードに数字が含まれない場合無効な状態であること' do
    user = User.new(password: 'A'+'a' * 5, password_confirmation: '1A'+'a' * 3)
    user.valid?
    expect(user.errors[:password]).to include('は半角6~12文字英大文字・小文字・数字それぞれ1文字以上含む必要があります')
  end

  it 'パスワードが5文字以下なら無効な状態であること' do
    user = User.new(password: '1A'+'a' * 3, password_confirmation: '1A'+'a' * 3)
    user.valid?
    expect(user.errors[:password]).to include('は半角6~12文字英大文字・小文字・数字それぞれ1文字以上含む必要があります')
  end

  it 'パスワードが13文字以上なら無効な状態であること' do
    user = User.new(password: '1A'+'a' * 11, password_confirmation: '1A'+'a' * 11)
    user.valid?
    expect(user.errors[:password]).to include('は半角6~12文字英大文字・小文字・数字それぞれ1文字以上含む必要があります')
  end

テストをしますが失敗します。

rspec spec/models/user_spec.rb

User
  パスワードに英小文字が含まれない場合無効な状態であること (FAILED - 1)
  パスワードに英大文字が含まれない場合無効な状態であること (FAILED - 2)
  パスワードに数字が含まれない場合無効な状態であること (FAILED - 3)
  パスワードが5文字以下なら無効な状態であること (FAILED - 4)
  パスワードが13文字以上なら無効な状態であること (FAILED - 5)

5 examples, 5 failures

2.コードを修正する

/app/model/user.rb
VALID_PASSWORD_REGEX =/\A(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[\d])\w{6,12}\z/
  validates :password, presence: true,
            format: { with: VALID_PASSWORD_REGEX,
             message: "は半角6~12文字英大文字・小文字・数字それぞれ1文字以上含む必要があります"}

VALID_PASSWORD_REGEXにformatのwithオプションに指定する正規表現をセットします。formatではwithオプションの正規表現と属性(パスワード)がマッチするか検証します。messageには失敗したときのカスタムエラーメッセージを設定できます。(railsを日本語化していないとエラーになると思いますので日本語を使う際は注意してください。)

これでテストします。(ユーザーが有効な状態であることも確認するテストも追加)

spec/mpdel/user_spec.rb
it '名前、メール、パスワードがあれば有効な状態であること' do
    user = User.new(
      name: 'Aaron',
      email: 'tster@example.com',
      password: 'foobar12A',
      password_confirmation: 'foobar12A'
    )
    expect(user).to be_valid
  end

以下略
rspec spec/models/user_spec.rb
名前、メール、パスワードがあれば有効な状態であること
  パスワードに英小文字が含まれない場合無効な状態であること
  パスワードに英大文字が含まれない場合無効な状態であること
  パスワードに数字が含まれない場合無効な状態であること
  パスワードが5文字以下なら無効な状態であること
  パスワードが13文字以上なら無効な状態であること

Finished in 0.38981 seconds (files took 3.59 seconds to load)
6 examples, 0 failures

これで期待するパスワードのバリデーションを追加することができました!

19
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
23