【问题标题】:Scala Play form validation: different forms for one case class - is it possible?Scala Play 表单验证:一个案例类的不同表单 - 可能吗?
【发布时间】:2013-05-29 14:25:17
【问题描述】:

我正在寻找一种方法来为一个案例类使用两种不同的形式。我试图用额外的构造函数来做到这一点,但失败了。看代码sn -p:

case class LoginDetails(password: String, field3: Option[Int], field4: String)

case class User(username: String, loginDetails: LoginDetails) {
   def this(username: String, password: String, field3: Option[Int], field4: String) = this(username, LoginDetails(password, field3, field4))
// some logic inside
    }

val loginDetailsForm = Form(
 mapping(
   "password" -> text,
   "field3" -> optional(number),
   "field4" -> text
 )(LoginDetails.apply)(LoginDetails.unapply))

val oldForm = Form(
 mapping(
   "username" -> email,
   "password" -> text,
   "field3" -> optional(number),
   "field4" -> text
 )(User.apply)(User.unapply))

val newForm = Form(
     mapping(
       "username" -> email,
       "loginDetails" -> loginDetailsForm.mapping
     )(User.apply)(User.unapply))

我想要做的是支持两个 API(新的和旧的),但是如果我将拥有同一个案例类的两个副本,我将不得不在其余的许多地方制作代码逻辑重复的代码。如果有办法做到这一点?

当然,给定的代码是行不通的,就像一个例子一样使用。

谢谢!

【问题讨论】:

    标签: forms scala playframework mapping playframework-2.0


    【解决方案1】:

    您可以尝试将方法 applyOldunapplyOld 添加到伴随对象,如下所示:

    case class User(username: String, loginDetails: LoginDetails)
    object User {
      def applyOld(username: String, password: String, field3: Option[Int], field4: String) = new User(username, LoginDetails(password, field3, field4))
      def unapplyOld(u: User): Option[(String, String, Option[Int], String)] =
        Some((u.username, u.loginDetails.password,  u.loginDetails.field3,  u.loginDetails.field4))
    }
    

    您只需要方法(String, String, Option[Int], String) => UserUser => Option[(String, String, Option[Int], String)],您可以将它们放置在您喜欢的任何地方。例如,您可以使用 applyunapply 方法创建对象 UserOld

    用法:

    val oldForm = Form(
     mapping(
       "username" -> email,
       "password" -> text,
       "field3" -> optional(number),
       "field4" -> text
     )(User.applyOld)(User.unapplyOld))
    
    val newForm = Form(
         mapping(
           "username" -> email,
           "loginDetails" -> loginDetailsForm.mapping
         )(User.apply)(User.unapply))
    

    【讨论】:

    • 明白了,谢谢。我希望可以在不制作伴生对象的情况下做到这一点。由于我有大约 100 个类,它们将同时支持这两个 API,所以我无法避免冗长。我会等一下,可能会有其他更优雅的答案,但我怀疑。然后,我会将您的答案标记为解决方案。再次感谢。
    • @britva:你必须以某种方式创建这两个函数。没有必要将它们放在伴随对象中。您甚至可以“就地”创建它们:mapping(...)((a, b, c, d) => ...)(user => Some((...)))。
    【解决方案2】:

    您可以直接在定义表单的地方执行应用/取消应用。这样你就不必向案例类添加任何新的构造函数了。

    val oldForm = Form(
      mapping(
        "username" -> email,
        "password" -> text,
        "field3" -> optional(number),
        "field4" -> text
      )(
        (username, password, field3, field4) =>
          User(username, LoginDetails(password, field3, field4))
      )(
        (user: User) =>
          Option(user.username, user.loginDetails.password, user.loginDetails.field3, user.loginDetails.field4)
      )
    )
    
    val newForm = Form(
      mapping(
        "username" -> email,
        "loginDetails" -> loginDetailsForm.mapping
      )(User.apply)(User.unapply))
    

    【讨论】:

      猜你喜欢
      • 2015-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-09
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多