Techioz Blog

Rails での空のパスワードに対する検証

概要

User モデルにパスワードの検証を追加しました。

validates :password, presence: true
validates :password, confirmation: { case_sensitive: true }

しかし、ユーザーの他のフィールドを更新しようとすると、パスワードが存在しないため、それらの検証によりトランザクションが無効になってしまいました。

少し調べた結果、パスワードが存在しない場合はこれらの検証をスキップできることがわかりました。

validates :password, presence: true, if: :validate_password?
validates :password, confirmation: { case_sensitive: true }, if: :validate_password?


def validate_password?
  password.present? || password_confirmation.present?
end

ただし、空のパスワードとパスワードの確認を送信すると、 validate_password? falseを返します。何が起こっているのかよくわかりません。

@user.update_attributes(password_reset_edit_params) は true を返します

どこ

password_reset_edit_params は <ActionController::Parameters {“password”=>““,”password_confirmation”=>““} が許可されています: true>

でも内側では

def validate_password?
  password.present? || password_confirmation.present?
end

パスワードとパスワード確認は nil と評価され、@user パスワードは空の文字列に更新されません。

私は Bcrypt を使用していることに言及しておく必要がありますが、@user.password は実際には常に nil として評価されますが、password_digest は利用可能です。

それで、解決策は何でしょうか?結局のところ、私の質問は単純に次のとおりだと思います。

パスワードを送信しようとしていないときにパスワード検証を無視し、空の文字列の送信時にパスワード検証を許可するにはどうすればよいですか?

空の文字列を渡さないようにコントローラーに条件を追加できることを思いつきましたが、この問題を解決する適切な方法が必要です。

ご協力をよろしくお願いいたします。ありがとう!

解決策

Bcrypt とダイジェストを使用する場合、たとえばモデルで使用できます。

has_secure_password
validates :password, length: { minimum: 8 }, allow_blank: true

この場合、検証はパスワードの設定と変更に対してのみ機能します。

パスワードを変更しない場合は、パスワードを入力する必要はありません。

別の方法

validates :password, presence: true, on: :create