5

我正在尝试在游戏中定义一种形式!2.0.4具有以下属性和约束:

  1. 表单处理重复的值(让我们方便地假设这些值是 type number)。所以这将使我们得到这样的结果:

    "numbers" -> list(number)
    
  2. 每个号码必须是唯一的,即对于所有其他提交的号码,它必须是唯一的,并且对于数据库中已经存在的号码必须是唯一的(这可以通过某些功能进行检查check(num: Int): Boolean)。

  3. 表单错误应该是特定于数字的,不是唯一的。我不希望出现“有重复号码”的一般表单错误。

最好的方法是什么?

4

2 回答 2

3

这里的诀窍是定义一个Constraint类似这个例子的自定义类型。Constraint然后可以使用自定义方法Mapping[T]来验证表单中的字段verifying

自定义Constraint包含返回 aValidationResultValid的逻辑Invalid。可以将错误消息传递给Invalid结果,您可以在其中指定数据库中重复或存在的内容。

有关自定义验证的部分,请参阅Play for Scala

- 创建约束

  //Make this lazy to prevent java.lang.ExceptionInInitializerError at runtime.
  lazy val uniqueNumbersConstraint = Constraint[String](Some("Unique numbers constraint"), "")(checkNumbers)

  //"Business Logic". 
  //Important part here is that the function returns a ValidationResult and complies with the signature for Constraint. i.e. f: (T) => ValidationResult
  //Return Valid if n in numbers is not in database and there are no duplicates.   
  //Otherwise return Invalid and an error message showing what numbers are in the database or duplicated. 
  def checkNumbers(numbers: String):ValidationResult  = {
    val splitNums = numbers.split(" ").toList.map(_.toInt)
    val dbnums  = splitNums.partition(database.contains(_))
    if(dbnums._1.isEmpty && uniquesAndDuplicates(splitNums)._2.isEmpty){
      Valid
    }else{
      val duplicates = uniquesAndDuplicates(dbnums._2)._2
      val error = "Database contains: " + dbnums._1 + ", duplicated values: " + duplicates
      Invalid(error)
    }
  }

- 使用自定义约束验证表单

  val helloForm = Form(
    tuple(
      "numbers" -> nonEmptyText.verifying(uniqueNumbersConstraint)
    ))

- 实用程序

  //Return unique values on left side and duplicate values on right side
  def uniquesAndDuplicates(numbers: List[Int]):Tuple2[List[Int], List[Int]] = {
    numbers.partition(i => numbers.indexOf (i) == numbers.lastIndexOf(i))
  }

  def checkNum(num: Int) = {
    database.contains(num) 
  }

  val database = List(5,6,7)

- ETC

注意我在表格中定义numbers为a String。当我将它定义为list(number)它不断评估为List(). 我认为这是一个有约束力的问题。这是一个相当简单的更改来使用List(1,2,3)而不是"1 2 3"如果使用list(number)作品。

- 样品

在此处输入图像描述 在此处输入图像描述 在此处输入图像描述

于 2012-11-21T07:54:56.997 回答
2

怎么样:

def validateUnique(input: List[Int]): ValidationResult = {

  // Assuming check return true if the input num doesn't exist yet
  def check(num: Int): Boolean = num % 2 == 0
  val unique = input.toSet
  val dbDuplicates = unique.filterNot(check)
  val formDuplicates = input.diff(unique.toSeq)
  val duplicates = (dbDuplicates ++ formDuplicates).toList

  duplicates match {
    case List() => Valid
    case _ => Invalid("Duplicates: " + duplicates.mkString(", "))
  }
}

val uniqueConstraint = Constraint[List[Int]](validateUnique(_))

然后你可以使用新的约束:

mapping(
  ...,
  "ints" -> list(number).verifying(uniqueConstraint)
  ...
于 2012-11-20T10:21:14.417 回答