【问题标题】:In Slick (Scala), how to refactor codes like this?在 Slick (Scala) 中,如何重构这样的代码?
【发布时间】:2015-06-18 17:37:36
【问题描述】:

我看到这样的代码:

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 看起来很有必要..

有人对如何重构这些代码有建议吗?谢谢!

【问题讨论】:

    标签: scala playframework playframework-2.0 slick slick-2.0


    【解决方案1】:

    首先:更好的缩进和打断长行。

    Slick-specific:从 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)
        }
    
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多