【问题标题】:Case classes, persistence and Play forms案例类、持久性和 Play 表单
【发布时间】:2015-01-31 02:35:38
【问题描述】:

在使用 Play 和 Anorm 创建基本应用程序的过程中,我在处理尚未保存到数据库的实体时遇到了问题。该表单显然没有 ID 字段,因此我无法使用案例类 apply 方法创建映射。我最终创建了两个类 - 一个用于持久化实体,一个用于尚未持久化,代码看起来像这样

case class EphemeralUser(email: String)

case class PersistentUser(id: Long, email: String)

val userForm = Form(mapping("email" -> text))(EphemeralUser.apply)(EphemeralUser.unapply)

def create(user: EphemeralUser): PersistentUser = { /* Save with Anorm */ }

有没有更优雅的方法来使用单个 case class User(id: Option[Long], email: String) 来处理它?甚至更好的是,某种消除代码重复的方法,因为我有点喜欢持久用户和临时用户是不同类型的事实。

【问题讨论】:

  • 两种不同的类型有什么问题?它们不一样。一个得救了一个没有。当您有一个带有 ID 的类型的实例时,您就知道它已被保存。当您有一个已保存类型的实例时,您就知道它有一个 ID。
  • @drstevens 我更喜欢两种类型的方法,因为它具有额外的类型安全性,但有很多样板。 defs 有一个特征,即所有字段和常见行为以及各个案例类的两个构造函数。虽然目前我不需要编辑表单,但那里似乎会有一些重复。

标签: scala playframework playframework-2.0


【解决方案1】:

我认为没有必要要求两种类型。将id 设为Option[Long] 就足够了。要测试模型是否已被持久化,只需要您检查 user.id.isDefined

然后您的Form 可以使用ignored 仍然利用applyunapply

case class User(id: Option[Long], email: String)

val userForm = Form {
    mapping(
        "id" -> ignored[Option[Long]](None),
        "email" -> email
    )(User.apply)(User.unapply)
}

【讨论】:

  • 我认为这是正确的做法,至少,这是我在工作中所做的;我的案例类倾向于将持久性 ID 定义为类型 Option[Long]。当然,这是假设您的持久性 ID 需要在数据模型中的应用程序中传递。
  • 我唯一不喜欢的是访问Option[Long] id 不太方便,但我愿意经常忍受。
猜你喜欢
  • 2012-10-07
  • 1970-01-01
  • 2017-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-10
  • 1970-01-01
  • 2012-12-19
相关资源
最近更新 更多