Scala 案例类、持久性和游戏形式

Scala 案例类、持久性和游戏形式,scala,playframework,playframework-2.0,Scala,Playframework,Playframework 2.0,在使用Play和Anorm创建基本应用程序的过程中,我遇到了一个问题,即处理尚未保存到数据库中的实体。表单显然没有ID字段,因此我无法使用case类apply方法创建映射。我最终创建了两个类——一个用于持久化实体,另一个用于尚未持久化的实体,代码如下所示 case class EphemeralUser(email: String) case class PersistentUser(id: Long, email: String) val userForm = Form(mapping("

在使用Play和Anorm创建基本应用程序的过程中,我遇到了一个问题,即处理尚未保存到数据库中的实体。表单显然没有ID字段,因此我无法使用case类
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 */ }

是否有一种更优雅的方法可以使用单个
案例类用户(id:Option[Long],email:String)
?或者更好的办法是,通过某种方式消除代码重复,因为我有点喜欢持久用户和临时用户是不同的类型。

我认为不需要两种类型。将
id
设为
选项[Long]
就足够了。要测试模型是否已持久化,只需检查
user.id.isDefined

您的
表单
可以使用
忽略
仍然利用
应用
不应用

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

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

我认为这是正确的做法,至少,这是我在工作中所做的;我的案例类倾向于将持久性ID定义为type
Option[Long]
。当然,这是假设您的持久性ID需要在数据模型中传递给您的应用程序。我唯一不喜欢的是,访问
选项[Long]
ID稍微不方便,但我愿意经常忍受。两种不同的类型有什么错?他们是不同的。一个得救了,一个没有。当您有一个ID为的类型实例时,您就知道它已保存。当你有一个已保存类型的实例时,你知道它有一个ID。@drstevens我更喜欢两种类型的方法,因为它有额外的类型安全性,但是有很多样板文件。有一个特性是
def
s所有字段和常见行为,以及各自案例类的两个构造函数。虽然目前我不需要编辑表单,但似乎会有一些重复。