根据Rails中的空白密码进行验证

时间:2019-03-22 14:23:01

标签: ruby-on-rails ruby validation activerecord bcrypt

我在User模型中添加了密码密码验证:

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

但是当我想更新users上的其他字段时,由于没有password,这些验证使交易无效。

通过一些研究,我意识到如果没有password,我可以跳过那些验证:

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"=>""} permitted: true>

但在里面

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

passwordpassword_confirmation的值为nil,我的@user密码不会更新为空字符串。

我应该提到我正在使用Bcrypt,实际上@user.password的总评估为nil,而password_digest可用。

那么解决方案是什么?最终我想我的问题很简单:

当我不尝试提交密码时如何忽略密码验证,但在提交空字符串时又允许这些验证?

在我看来,我可以在控制器中添加不允许传递空字符串的条件,但是必须有一种巧妙的方法来解决此问题。

非常感谢您的帮助。谢谢!

3 个答案:

答案 0 :(得分:1)

在Rails中,您不是在验证参数,而是在验证模型。

请勿“如果密码不存在,请跳过验证”。这就是验证的目的。验证是为了验证模型,而不是参数。如果模型的密码为空,并且需要输入密码,则该模型无效。总是。

  

但是当我想更新用户的其他字段时,由于没有密码,这些验证使交易无效。

不是因为密码不存在,而是因为User实例中没有密码。它应该工作的方式是:

  1. 使用密码创建用户并进行验证:User.create(name: "Me", password: "something that isn't nil")
  2. 用户已更新:User.update(name: "New name") # password is inside the model still so it is still valid

这就是它的工作方式。如果您希望用户能够使用nil /空密码,那么您不应尝试在模型中放置状态验证。

答案 1 :(得分:1)

如果使用Bcrypt和摘要,则可以在模型中使用

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

在这种情况下,验证仅适用于设置和更改密码。

如果您不更改密码,则无需输入密码。

另一种方式

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

答案 2 :(得分:0)

最终,我只是在验证用户模型上的密码格式和确认:

<form>
    <div class="ss-item-required">
      <label for="userName">Question: What is your name?</label>
      <input type="text" name="name" id="userName">
    </div>
    <div class="ss-item-required">
      <label for="email">Question: What is your email?</label>
      <input type="text" name="email" id="email">
    </div>
    <div class="ss-item-required">
      <label for="address">Question: What is your address?</label>
      <textarea name="address" rows="8" cols="75" id="address"></textarea>
    </div>
     <div class="ss-item-required">
      <label for="Check_0">Do you agree to out terms?
        <input type="checkbox" name="Check_0">
      </label>
    </div>

    <a href="#" onclick="formcheck(); return false">Submit</a>
 </form>
 
 <script>
 function formcheck() {
  // Get all the required elements into an Array
  var fields = [].slice.call(document.querySelectorAll(".ss-item-required > *"));
  
   // Loop over the array:
   fields.forEach(function(field) {
     // Check for text boxes or textareas that have no value
     if ((field.type === "text" || field.nodeName.toLowerCase() === "textarea")
          && !field.value){
       alert(field.name + ' is required');
       // Then check for checkboxes that aren't checked
     } else if(field.type === "checkbox" && !field.checked){
       alert("You must agree to the terms to continue.");
     }
   }); 
}
 </script>

并根据控制器中的空白密码/ password_confirmation清除输入数据。

validates :password,  confirmation: true,
                      length: {within: 6..40},
                      allow_blank: true