我如何在Play表格中要求布尔值?

时间:2013-05-09 20:34:40

标签: forms scala playframework boolean require

我正在使用Play 2.1.0。我正在尝试创建一个接受POST请求的Action,并要求在请求体中需要一个布尔值。现在发生的事情是,即使我不提供参数,Action也会获得错误的值。测试代码:

// /post/boolean/single routes to this method
def postTestBooleanSingle = Action { implicit request =>
    val form = Form("flag" -> boolean)
    form.bindFromRequest.fold(
        formWithErrors =>
            BadRequest(formWithErrors.errors map (fe => fe.key + ": " + fe.message) mkString ", "),
        flag => Ok(f"got $flag%b")
    )
}

// /post/num/single routes to this method
def postTestNumSingle = Action { implicit request =>
    val form = Form("num" -> number)
    form.bindFromRequest.fold(
        formWithErrors => 
            BadRequest(formWithErrors.errors map (fe => fe.key + ": " + fe.message) mkString ", "),
        num => Ok(f"got $num%d")
    )
}

$ curl -XPOST -d "num=42" http://localhost:9000/post/num/single
got 42
$ curl -XPOST http://localhost:9000/post/num/single
num: error.required // didn't provide num so i get an error
$ curl -XPOST -d "flag=true" http://localhost:9000/post/boolean/single
got true
$ curl -XPOST http://localhost:9000/post/boolean/single
got false // ???

我如何需要布尔参数?

1 个答案:

答案 0 :(得分:4)

我不知道为什么,但在没有任何参数的情况下,布尔类型的表格映射似乎默认为false。

以下是播放源中Format.scala的代码片段:

/**
 * Default formatter for the `Boolean` type.
 */
implicit def booleanFormat: Formatter[Boolean] = new Formatter[Boolean] {

  override val format = Some(("format.boolean", Nil))

  def bind(key: String, data: Map[String, String]) = {
    Right(data.get(key).getOrElse("false")).right.flatMap {
      case "true" => Right(true)
      case "false" => Right(false)
      case _ => Left(Seq(FormError(key, "error.boolean", Nil)))
    }
  }

  def unbind(key: String, value: Boolean) = Map(key -> value.toString)
}

这里的重要部分是data.get(key).getOrElse("false")。在没有任何输入的情况下,它默认布尔值为false。您将需要创建一个自定义格式化程序,并使用它来定义布尔值的自定义绑定。

我会留给你把它们放在你的代码库中的好地方,但你的拼图应该是这样的:

// This is the custom formatter to support your custom mapping.
import play.api.data.format.Formatter
implicit def requiredBooleanFormatter: Formatter[Boolean] = new Formatter[Boolean] {

  override val format = Some(("format.boolean", Nil))

  def bind(key: String, data: Map[String, String]) = {
    Right(data.get(key).getOrElse("")).right.flatMap {
      case "true" => Right(true)
      case "false" => Right(false)
      case _ => Left(Seq(FormError(key, "error.boolean", Nil)))
    }
  }

  def unbind(key: String, value: Boolean) = Map(key -> value.toString)
}

// This is your custom mapping to be used in the form
import play.api.data.Forms
val requiredBoolean: Mapping[Boolean] = Forms.of[Boolean](requiredBooleanFormatter)

请注意从.getOrElse("false").getOrElse("")的更改。代码几乎相同,但我们现在将空值推送到错误捕获器,而不是使它们取false值。 (注意:为清楚起见,我在此示例中明确指定了requiredBooleanFormatter,但由于requiredBooleanFormatter是隐式的并且在范围内,因此您不必这样做。)

现在,您只需在表单中使用requiredBoolean代替boolean,即要求在请求中明确设置参数。