Play Framework Form只有18个参数

Mag*_*nus 6 scala playframework playframework-2.0

我观察到,当我向Play Framework Form-class添加超过18个参数时,我得到一个很长的(并且对我来说难以理解)编译错误.

这是文件限制吗?我需要在表单帖子中接收多达29个参数.我没有决定参数的设计和数量,因为我正在从开放标准实现协议.

我这样映射:

val registration = Form(mapping(
    "client_type" -> nonEmptyText,
    "client_id" -> optional(nonEmptyText),
    ... up to 29 args, all optional(nonEmptyText)
    ){ (clientType, clientId ...) => RegistrationRequest(clientType, clientId ...) }
     { req => None })
Run Code Online (Sandbox Code Playgroud)

我的策略是以这种方式进行映射,而不是应用/取消应用,并创建一个案例类的层次结构.原因是在Case类中解决了22个参数限制,这是我遇到的第一个看似任意的限制.最多18个args映射工作,之后我得到一个很长的编译错误.

可以在此处找到错误消息(包括太长时间):https://gist.github.com/2928297

我正在寻找关于如何解决这个限制的建议.我知道在Post表单中发送29个参数是不好的设计,但它应该仍然可行.


哈克/变通方法/解决方案

好的,这是我的黑客一起解决方法(写这篇文章比实施花了更长的时间,我在这上面砍了大约30分钟)

我编写了预处理请求参数的函数,并添加了一个组前缀来对某些参数进行分组.然后我使用生成的Map [String,String]并继续使用表单类进行处理,像往常一样进行验证等.这允许我在映射中使用嵌套的case类,并且低于18 params限制.

当心:未来的丑陋代码!我可能不应该像这样显示早期的hacky代码,但我希望它能帮助其他想要解决方法的人.

def preprocessFormParams(prefix:String, replace:String)(implicit request:Request[AnyContent]):Map[String, String] = request.body.asFormUrlEncoded.map( _.filterKeys( _.startsWith(prefix)).map( m => m._1.patch(0, replace, prefix.length)  -> m._2.head )).getOrElse(Map.empty)
def unprocessedFormParams(prefixes:Set[String])(implicit request:Request[AnyContent]):Map[String, String] = request.body.asFormUrlEncoded.map( _.filterKeys( !prefixes.contains(_) ).map( m => m._1 -> m._2.head )).getOrElse(Map.empty)
Run Code Online (Sandbox Code Playgroud)

所以这些函数可能应该用于理解或拆分,但是这里有:preprocessedFormParms接受前缀并替换它:

val clientParams = preprocessFormParams("client_", "client.")
("client_id" -> "val1", "client_type" -> "val2") becomes ("client.id" -> "val1", "client.type" -> "val2")
Run Code Online (Sandbox Code Playgroud)

当我有group.key1,group.key2形式的参数时,我可以像这样在表单中嵌套case类

Form(mapping("client" -> mapping("type" -> nonEmptyText
    "id" -> optional(nonEmptyText),
    "secret" -> optional(nonEmptyText))
    (RegisterClient.apply)(RegisterClient.unapply)
    ... more params ...)
    (RegisterRequest.apply)(RegisterRequest.unapply)
Run Code Online (Sandbox Code Playgroud)

在我的行动中,我继续过滤掉我的每个小组

implicit request =>
val clientParams = preprocessFormParams("client_", "client.")       
val applicationParams = preprocessFormParams("application_", "application.")
val unprocessedParams = unprocessedFormParams(Set("client_", "application_"))
val processedForm = clientParams ++ applicationParams ++ unprocessedParams
Run Code Online (Sandbox Code Playgroud)

最后,我可以像平常一样应用我的表单,但现在我得到了嵌套结构,减少了参数的数量,并希望使案例类更易于管理.

clientRegistrationForm.bind(processedForm).fold( ... )
Run Code Online (Sandbox Code Playgroud)

使用此方法可以减少参数数量.如果你的参数没有像我的问题那样容易分组的相同前缀,那么你仍然可以使用相同的基本方法,但过滤其他标准.

vir*_*yes 3

几周前我就这个问题开了一张票。

如果你投票支持它,也许 Play 开发者会关注它。

怀疑它在他们的优先级列表中排名很高(不幸的是,它或多或少只是复制粘贴到 19、20、21 和 22 映射 [T] 上)

如果你绝望了,你可以分叉 Play;否则,请提出解决方法,例如,利用嵌套表单或将 > 22 个字段模型拆分为单独的表单。