Play 2.0表单(scala)的自定义验证

4

我正在编写一个小的业余应用程序。在我的应用程序中,我想让人们拥有一个用户ID(就像我的在stackoverflow上是niklassaers一样),如果该ID已被使用,则希望用户收到错误提示,以便其选择另一个ID。

以下是我的注册对象,它在“mapping(”一行给我一个错误:“缺少方法映射的参数;如果要将其视为部分应用函数,请在此方法后跟 `_' ”

object Signup extends Controller {

  val userForm: Form[UserProfile] = Form(
    mapping(
      "userId" -> nonEmptyText,
      "passwordHash" -> nonEmptyText,
      "email" -> email
    ) verifying (
      "ThisIsATest", { case(userId, passwordHash, email) => true }
      // "UserID already taken", { DBService.exists(UserProfile.getClass().getName(), userId) }
      )(UserProfile.apply)(UserProfile.unapply))


  def index = Action {

    Ok(views.html.signup(userForm))
  }

  def register = Action { implicit request =>
    userForm.bindFromRequest.fold(
      errors => BadRequest(views.html.signup(errors)),
      user => Redirect(routes.Profile.index))
  }
}

如您所见,我使用了一个测试验证来替换我的查找服务,该验证只返回true,以使示例更简单。为了完整起见,以下是我的UserDetail案例类:

case class UserProfile(
                   userId : String,
                   email: String,
                   passwordHash: String)

我是一个Scala新手和Play框架新手,如果这是一个非常琐碎的问题,则十分抱歉。
  1. 我做错了什么导致出现此错误?

  2. 这是添加自己的验证规则的正确方法吗?

  3. 跟进问题:如果一切顺利,我该如何重定向到引用刚刚验证的表单的页面?

问候,
Nik

在 case class 定义中去掉 vals,因为 case class 的属性默认是不可变的。 - virtualeyes
谢谢您的评论,我已经删除了vals,但这不会改变任何东西,对吧?我仍然得到相同的编译错误。 - niklassaers
3个回答

5
最终解决了这个问题:验证不是在映射之后进行的,而是在约束时进行的。因此,应该是这样的:
"userId" -> nonEmptyText.verifying( "UserID already taken", userId => DBService.exists(UserProfile.getClass().getName().replace("$", ""), userId) == false ),

我希望这能帮助到其他遇到同样问题的人 :-)


2
实际上,我相信您可以在表单本身上进行全局验证。我自己还没有尝试过,但已经看到了您尝试的“尾随”验证方式。 - virtualeyes
谢谢这个解决方案,它确实可行,除了我必须将条件更改为 getOrElse(None) == None。 - Anthony McCormick

4
虽然有点晚,但无论如何......
您可以对整个“表单后备对象”进行验证,而不仅仅是一个单独的字段,这与您在问题描述中发布的第一段代码类似。问题在于您的验证块需要放在应用/取消应用语句之后。
case class UserRegistration(username: String, password1: String, password2: String)

val loginForm = Form(
  mapping(
    "username" -> email,
    "password1" -> text,
    "password2" -> text
  )
  (UserRegistration.apply)(UserRegistration.unapply)
  verifying ("Passwords must match", f => f.password1 == f.password2)
)

我不知道自你回答以来发生了什么变化,但现在它已经不再工作了,我们得到了一个错误信息:无名函数的参数类型必须是完全已知的。 - Ashesh
我刚刚使用最新的Play版本(2.3.4)尝试了那段代码,看起来没问题。你连编译都通过不了吗? - janne

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接