scala - How do I require booleans in Play forms? -
i'm using play 2.1.0. i'm trying create action accepts post request , requires boolean required in request body. what's happening if don't supply param action gets false value. test code:
// /post/boolean/single routes 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 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 error $ curl -xpost -d "flag=true" http://localhost:9000/post/boolean/single got true $ curl -xpost http://localhost:9000/post/boolean/single got false // ???
how require boolean parameter?
i'm not sure why, form mapping boolean type appears default false in absence of parameters.
here's snippet responsible format.scala in play source:
/** * default formatter `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) }
the important part here data.get(key).getorelse("false")
. in absence of input, defaults booleans false. you'll want create custom formatter , use define custom binding booleans.
i'll leave put these in places in code base, pieces of puzzle should this:
// custom formatter support 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) } // custom mapping used in form import play.api.data.forms val requiredboolean: mapping[boolean] = forms.of[boolean](requiredbooleanformatter)
notice change .getorelse("false")
.getorelse("")
. code same, we're pushing empty values error catcher instead of making them take false
value. (note: explicitly specify requiredbooleanformatter
in example clarity, since requiredbooleanformatter
implicit , in scope, don't have to.)
now can use requiredboolean
instead of boolean
in forms require param explicitly set in request.
Comments
Post a Comment