我在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
password
和password_confirmation
的值为nil
,我的@user
密码不会更新为空字符串。
我应该提到我正在使用Bcrypt,实际上@user.password
的总评估为nil
,而password_digest
可用。
那么解决方案是什么?最终我想我的问题很简单:
当我不尝试提交密码时如何忽略密码验证,但在提交空字符串时又允许这些验证?
在我看来,我可以在控制器中添加不允许传递空字符串的条件,但是必须有一种巧妙的方法来解决此问题。
非常感谢您的帮助。谢谢!
答案 0 :(得分:1)
在Rails中,您不是在验证参数,而是在验证模型。
请勿“如果密码不存在,请跳过验证”。这就是验证的目的。验证是为了验证模型,而不是参数。如果模型的密码为空,并且需要输入密码,则该模型无效。总是。
但是当我想更新用户的其他字段时,由于没有密码,这些验证使交易无效。
不是因为密码不存在,而是因为User实例中没有密码。它应该工作的方式是:
User.create(name: "Me", password: "something that isn't nil")
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