Play Framework Form 只有 18 个参数 [英] Play Framework Form only 18 params

查看:14
本文介绍了Play Framework Form 只有 18 个参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have observed that when I add more than 18 parameters to a Play Framework Form-class I get a long (and for me incomprehensible) compilation error.

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

Is this a documented limitation? I need to take in as much as 29 parameters in a form post. I don't decide on the design and number of parameters as I am implementing a protocol from an open standard.

我是这样映射的:

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 })

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

My strategy was to do the mapping this way instead of apply/unapply and create an heirarchy of case classes. The reason is to work around the 22 arguments limit in Case classes, which was the first seemingly arbitrary limit I ran into. Up to 18 args mapping works, after that I get a long compilation error.

错误信息可以在这里找到(太长无法包含):https://gist.github.com/2928297

The error message can be found here (too long to include): https://gist.github.com/2928297

我正在寻找有关如何解决此限制的建议.我知道在表单 Post 中发送 29 个参数是糟糕的设计,但它应该仍然是可能的.

I'm looking for suggestions on how I can get around this limitation. I know it is bad design to send in 29 parameters in a form Post, but it should still be possible.

破解/解决方法/解决方案

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

Ok, here is my hacked together workaround (writing this post took much longer than implementing, I hacked for ~30min on this)

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

I wrote functions that preprocesses the request params and adds a group prefix to group certain params. I then use the resulting Map[String, String] and continue processing with the form class, doing validation etc as usual. This allows me to use nested case classes in the mapping and get below the 18 params limit.

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

Beware: ugly code ahead! I should probably not show early hacky code like this, but I'm hoping it will help someone else who wants a workaround.

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)

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

So these functions should probably be for comprehensions or split up, but here goes: preprocessedFormParms takes a prefix and replaces it:

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

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

When I have the parameters in the form of group.key1, group.key2 I can nest the case classes in the form like so

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

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

In my action I go ahead and filter out each of my groups

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

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

Lastly I can apply my form like normal but now I get the nested structure I that reduces the number of arguments and hopefully makes the case class more manageable.

clientRegistrationForm.bind(processedForm).fold( ... )

使用这种方法可以减少参数的数量.如果您的参数没有与我的问题一样易于分组的相同前缀,那么您仍然可以使用相同的基本方法,但根据其他条件进行过滤.

Using this approach you can keep the number of parameters down. If your parameters don't have the same prefix for easy grouping like my problem, then you can still use the same basic approach but filter on other criterias.

推荐答案

I 几周前就这个问题开了一张票.

如果你投了赞成票,也许 Play 开发者会看到它.

If you vote for it, perhaps it will get a look from Play devs.

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

Doubt it's high on their priority list (unfortunate given that it's more or less just a copy-paste to tack on the 19, 20, 21, and 22 Mapping[T])

如果你不顾一切,你可以fork Play;否则,想出一个解决方法,例如,使用嵌套表单或将 > 22 个字段模型拆分为单独的表单.

If you are desperate, you could fork Play; otherwise, come up with a workaround, for example, utilizing nested forms or splitting up > 22 field model into separate forms.

这篇关于Play Framework Form 只有 18 个参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆