我試圖通過遠程驗證服務來驗證用戶。我寫的輔助方法來發送消息給服務,並等待結果:播放2格式限制
def authenticateAwait(email: String,
password: String
): Either[String, Option[User]] = {
try {
val future = authenticate(email, password)
Right(Await.result(future, timeout.duration))
} catch {
case _ ⇒ Left("Unable to connect to authentication server")
}
}
它與錯誤描述返回Left[String]
如果無法發送消息,或者沒有迴應。如果收到服務響應,則返回Right[Option[User]]
。服務根據驗證結果以Option[User]
響應。
要與一對夫婦驗證的執行我創建的形式實際驗證,那就是:
val loginForm = Form(
tuple(
"email" → email,
"password" → nonEmptyText
) verifying ("Invalid email or password", result => result match {
case (email, password) ⇒
User.authenticateAwait(email, password) match {
case Left(_) ⇒ true
case Right(optUser) ⇒ optUser.isDefined
}
}) verifying ("Unable to connect to authentication server", result => result match {
case (email, password) ⇒
User.authenticateAwait(email, password) match {
case Left(_) ⇒ false
case Right(optUser) ⇒ true
}
})
)
有一件事我擔心這段代碼,它調用authenticateAwait
兩次。這意味着每個驗證只會發送兩條消息。我真正需要的是調用authenticateAwait
一次,存儲結果並對其執行各種驗證。似乎沒有簡單的解決方案。
要執行身份驗證,需要訪問表單字段,這意味着應該綁定表單然後進行驗證,但是沒有辦法將錯誤附加到現有表單(我錯了嗎?)。
錯誤只能在創建時附加到表單上,所以我應該在驗證器中執行驗證,但是會出現上述問題。
我附帶的臨時解決方案是在裏面定義一個方法和一個var
。
def loginForm = {
var authResponse: Either[String, Option[commons.User]] = null
Form(
tuple(
"email" → email,
"password" → nonEmptyText
) verifying ("Invalid email or password", result ⇒ result match {
case (email, password) ⇒
authResponse = User.authenticateAwait(email, password)
authResponse match {
case Left(_) ⇒ true
case Right(optUser) ⇒ optUser.isDefined
}
}) verifying ("Unable to connect to authentication server", result ⇒ result match {
case (email, password) ⇒
authResponse match {
case Left(_) ⇒ false
case Right(optUser) ⇒ true
}
})
)
}
這顯然是一種破解。有沒有更好的解決方案?
更新: 在我看來,窗體應該只對輸入進行消毒,但認證應該稍後在窗體外進行。 問題是,錯誤作爲Form
的一部分發送到視圖,並且不可能將錯誤附加到現有表單。有沒有簡單的方法來創建新的表單也有錯誤。
它被稱爲AJAX;使用它,你不會創建ginormous代碼塊試圖解決不存在的問題(提示:不需要創建一個新的表單) – virtualeyes