我正在通過Michael Hartl的Ruby on Rails教程開展工作,併產生了一個有趣的困境。我會做出錯誤的事情,所以我需要你的幫助來找到問題。密碼驗證在兩個相反的場景中失敗
問題圍繞User
模型中的密碼屬性的驗證。此屬性的初始驗證是:
validates :password, presence: true,
confirmation: true,
length: { minimum: 6 }
這需要密碼的最小長度,並且旨在滿足新用戶創建其實例的情況。
我已經創建了以下測試(我希望我已經使用了Rspec!)。這些測試檢查驗證工作:
test "password must not be blank or made up of spaces" do
@user.password = @user.password_confirmation = " "
assert_not @user.valid?
end
test "password must not be empty/nil" do
@user.password = @user.password_confirmation = ""
assert_not @user.valid?
end
因此,我們正在檢查密碼字段不能包含空格或零條目。通過當前的驗證,這些測試通過。一切都很好。
我已經發展到允許用戶編輯他們的個人資料。這使用戶可以更改他們的名字,電子郵件地址和密碼/確認,如果他們選擇。爲了讓用戶不更改其密碼,如果他們不想要,額外的驗證被添加到模型中的密碼屬性,增加allow_blank: true
如:
validates :password, presence: true,
confirmation: true,
length: { minimum: 6 },
allow_blank: true # added this!
因此,用戶可以現在如果他們不想更改他們的個人資料,他們在編輯他們的個人資料時將兩個密碼字段留空。這滿足了測試:
test "successful edit" do
log_in_as @user
get edit_user_path(@user)
assert_template 'users/edit'
name = "Foo Bar"
email = "[email protected]"
patch user_path(@user), params: { user: { name: name,
email: email,
password: "",
password_confirmation: "" } }
assert_not flash.empty?
assert_redirected_to @user
@user.reload
assert_equal @user.name, name
assert_equal @user.email, email
end
這使得用戶編輯只是他們的名字&電子郵件,並通過他們留下兩個密碼字段爲空,沒有必要改變自己的password
。如上所示,這會在長時間通過測試中引發FAIL,例如:
test "password must not be blank or made up of spaces" do
@user.password = @user.password_confirmation = " "
assert_not @user.valid?
end
測試失敗,因爲用戶已驗證。略有不同的測試,測試對於nil
,不是空白,通過:
test "password must not be empty/nil" do
@user.password = @user.password_confirmation = ""
assert_not @user.valid?
end
所以「」
密碼被捕獲但「 「
密碼工作正常創建新用戶或編輯現有用戶。
將allow_blank: true
添加到用戶模型驗證密碼似乎已經造成了這種情況。所以,我被困在兩次測試失敗之間。如果我忽略allow_blank: true
,測試失敗(全測試上面粘貼):
test "successful edit" do
.
.
patch user_path(@user), params: { user:
{ name: name,
email: email,
password: "",
password_confirmation: "" } }
.
assert_equal @user.name, name
assert_equal @user.email, email
end
發送空白password
和password_confirmation
測試失敗,因爲它不允許爲空。
添加驗證內allow_blank: true
失敗此測試:
test "password must not be blank or made up of spaces" do
@user.password = @user.password_confirmation = " "
assert_not @user.valid?
end
這失敗允許用戶用由空格的密碼來創建。 A nil
密碼,即根本沒有字符,是不允許的。該測試有效。
這使得我必須決定用戶必須更改/重複他們的兩個密碼字段,如果他們編輯他們的個人資料,或者允許用戶可以使用由一個空格組成的密碼註冊的場景或許多空間,如本次測試沒有拋出:
test "password must not be blank or made up of spaces" do
@user.password = @user.password_confirmation = " "
assert_not @user.valid?
end
添加的allow_blank: true
繞過這個測試或一般的驗證。接受任何數量空間的password
這是違反模型中的驗證。這怎麼可能?
任何想法如何更好地測試(除了使用Rspec!)。我向你提供更多的知識。
TIA。
[編輯]
的建議在下面的意見修改了我的測試套件綠色。這是由於套件不足。爲了測試不成功的整合,建議代碼測試一氣呵成多種方案,如:
test "unsuccessful edit with multiple errors" do
log_in_as @user
get edit_user_path(@user)
assert_template 'users/edit'
patch user_path(@user), params: { user:
{ name: "",
email: "[email protected]",
password: "foo",
password_confirmation: "bar" } }
assert_template 'users/edit'
assert_select 'div.alert', "The form contains 3 errors."
end
的關鍵部分在這裏越來越期待錯誤的號碼是否正確,這樣assert_select
給出正確的結果。我沒有。錯誤應該是空白名稱,無效的電子郵件格式,密碼太短,pwd &確認不匹配。沒有顯示短密碼的錯誤。
我決定抽出兩個測試來證明驗證密碼長度和存在的失敗。 allow_blank
的要點是在編輯用戶配置文件時允許密碼&確認字段有沒有,因此在每次編輯用戶配置文件時都不一定要輸入密碼。這些測試包括:
test "unsuccessful edit with short password" do
log_in_as @user
get edit_user_path(@user)
assert_template 'users/edit'
patch user_path(@user), params: { user:
{ name: @user.name,
email: "[email protected]",
password: "foo",
password_confirmation: "foo" } }
assert_select 'div.alert', "The form contains 1 error."
end
test "unsuccessful edit with blank (spaces) password" do
log_in_as @user
get edit_user_path(@user)
assert_template 'users/edit'
patch user_path(@user), params: { user:
{ name: @user.name,
email: "[email protected]",
password: " ",
password_confirmation: " " } }
assert_select 'div.alert', "The form contains 1 error."
end
如果密碼爲改變,那麼驗證規則應適用,即密碼不應該是空白,必須有一個最小長度。這不是教程本書建議的代碼或使用on: :create
和on: :edit
的修改代碼。
https://stackoverflow.com/questions/5123972/ruby-on-rails-password-validation考慮在這個問題上的答案。 – MisterCal
在這個問題中有一些可選的實現@MisterCal。除了試圖找到一個可行的解決方案,OP還提出了一個問題,即現有的驗證最小長度和非空白度的方法是在'BCrypt'應該是代碼中的一個點添加'allow_blank:true'來重寫爲新用戶捕獲非空白。事實上,'update'行動並沒有繞過驗證,因爲新用戶將(應該)已經遵守驗證規則並且具有驗證的密碼。那麼,這個添加如何允許創建一個與驗證規則相反的新用戶呢? – OnlySteveH
您只能指定'on::create'語句。然後創建另一個驗證,該驗證在::edit'上沒有'allow_blank'語句。 – MisterCal