我看到这样的代码:
trait LoginInfoRepoImpl extends LoginInfoRepo {
def loginInfoRepository = new LoginInfoRepository {
private val loginInfoTable = TableQuery[LoginInfoTable]
// return a LoginID
def save(userLoginInfo: userLoginInfo): Future[userLoginID] = Future {
val newRecord = DB.withSession { implicit session =>
loginInfoTable.filter(
l => l.userID === userLoginInfo.userID &&
(l.deviceID === userLoginInfo.deviceID || (l.deviceID.isEmpty && userLoginInfo.userID.isEmpty))).list.headOption.fold {
val newSubID = loginInfoTable.filter(l => l.userID === userLoginInfo.userID).sortBy(_.subID.desc).take(1).map(_.subID).list.headOption.getOrElse(0) + 1
(loginInfoTable returning loginInfoTable) += LoginInfoRecord(userLoginInfo.userID, newSubID, userLoginInfo.deviceID, userLoginInfo.userAgent, getCurrentTime)
} { l =>
// to do : update time
val q = for (l <- loginInfoTable if l.userID === userLoginInfo.userID && ((l.deviceID === userLoginInfo.deviceID)
|| (l.deviceID.isEmpty && userLoginInfo.userID.isEmpty)))
yield l.lastLoginTime
q.updateReturning(loginInfoTable.map(identity), getCurrentTime).head
}
}
userLoginID(newRecord.userID, newRecord.subID.toString)
}
}
}
对我来说这看起来有些怪异。我发现很多东西都挤在一条线上。另外,我发现l.deviceID
的类型为Column[Option[String]]
,而userLoginInfo.deviceID
的类型为Option[String]
,如果它们都是None
,则它们不相等。因此,l.device.isEmpty
看起来是必要的..
有人有关于如何重构这些代码的建议吗?谢谢!
答案 0 :(得分:0)
首先:更好的缩进和打破长线。
特定于Slick:从withSession块中提取查询并将其重用于共享逻辑。使用firstOption而不是.list.headOption。
旁注:由于您是基于旧ID生成ID,因此您可能希望使用事务或使用数据库提供的更有效的方法。
trait LoginInfoRepoImpl extends LoginInfoRepo {
def loginInfoRepository = new LoginInfoRepository {
private val loginInfoTable = TableQuery[LoginInfoTable]
// return a LoginID
def save(userLoginInfo: userLoginInfo): Future[userLoginID] = Future {
val userLoginInfoQuery = loginInfoTable.filter(l => l.userID === userLoginInfo.userID)
val deviceLoginInfoQuery = userLoginInfoQuery.filter(
l =>
l.deviceID === userLoginInfo.deviceID ||
(
l.deviceID.isEmpty && userLoginInfo.userID.isEmpty
)
)
val subIdQuery = userLoginInfoQuery.sortBy(_.subID.desc).map(_.subID)
val newRecord = DB.withTransaction{ implicit session =>
deviceLoginInfoQuery
.firstOption
.fold {
val newSubID = subIdQuery.firstOption.getOrElse(0) + 1
val newLoginInfo = LoginInfoRecord(userLoginInfo.userID, newSubID, userLoginInfo.deviceID, userLoginInfo.userAgent, getCurrentTime)
(loginInfoTable returning loginInfoTable) += newLoginInfo
}( _ =>
// to do : update time
deviceLoginInfoQuery
.map(_.lastLoginTime)
.updateReturning(loginInfoTable.map(identity), getCurrentTime)
.head
)
}
userLoginID(newRecord.userID, newRecord.subID.toString)
}
}
}