簡單的代碼,應該通過檢查用戶,用戶處於活動狀態,並在那之後更新上次登錄日期時間。斯卡拉異步/回調代碼重寫
def authenticate() = Action.async { implicit request =>
loginForm.bindFromRequest.fold(
errors => Future.successful(BadRequest(views.html.logon(errors))),
usersData =>{
val cursor = this.collection.find(BSONDocument("name" -> usersData._1)).one[Account].map(_.filter(p=>p.password == hashedPass(usersData._2, usersData._1)))
cursor.flatMap(p => p match {
case None => Future.successful(BadRequest(views.html.logon(loginForm.withGlobalError("user/pass incorect!!!"))))
case Some(user) => {
if(!user.active)
Future.successful(BadRequest(views.html.logon(loginForm.withGlobalError("inactive!!!"))))
else collection.update(BSONDocument("_id" -> user.id),
BSONDocument("$set" ->
BSONDocument("lastLogin" -> BSONDateTime(new org.joda.time.DateTime().getMillis()))))
.flatMap(x => gotoLoginSucceeded(user.id.stringify))
}
})
})
}
如何將它重寫爲flat flatmap/map spaghetti?
另一種解決方案
def authenticate() = AsyncStack { implicit request =>
loginForm.bindFromRequest.fold(
errors => Future.successful(BadRequest(views.html.logon(errors))),
usersData =>{
for{
user <- this.collection.find(BSONDocument("name" -> usersData._1)).one[Account].map(_.filter(p=>p.password == hashedPass(usersData._2, usersData._1)))
update <- {
lazy val update = collection.update(BSONDocument("_id" -> user.get.id),
BSONDocument("$set" ->
BSONDocument("lastLogin" -> BSONDateTime(new org.joda.time.DateTime().getMillis()))))
update
}
result <- {
lazy val result = gotoLoginSucceeded(user.get.id.stringify)
result
}
} yield
if(user.isEmpty) BadRequest(views.html.logon(loginForm.withGlobalError("login\pass mismatch")))
else if(!user.get.active) BadRequest(views.html.logon(loginForm.withGlobalError("inactive")))
else if(update.err.isEmpty) result
else InternalServerError(views.html.logon(loginForm.withGlobalError("server error")))
})
}
如何將它分解爲幾個較小的功能呢? – vptheron
這看起來對我來說是非常好的代碼。如EECOLOR所做的那樣,它可能會從將某些塊重構爲方法中受益,但除此之外,我看不出有什麼問題。這是什麼讓你煩惱 –