Форма Play Framework только 18 параметров

Я заметил, что когда я добавляю более 18 параметров в класс формы Play Framework, я получаю длинную (и непонятную для меня) ошибку компиляции.

Это задокументированное ограничение? Мне нужно принять до 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 })

Моя стратегия заключалась в том, чтобы сделать отображение таким образом, вместо применения/отмены применения и создания иерархии классов case. Причина в том, чтобы обойти ограничение в 22 аргумента в классах Case, которое было первым, казалось бы, произвольным ограничением, с которым я столкнулся. Работает сопоставление до 18 аргументов, после чего я получаю длинную ошибку компиляции.

Сообщение об ошибке можно найти здесь (слишком длинное, чтобы его включать): https://gist.github.com/2928297

Я ищу предложения о том, как обойти это ограничение. Я знаю, что отправлять 29 параметров в форму Post — плохой дизайн, но это все же возможно.


Взлом/Обходной путь/Решение

Хорошо, вот мой собранный обходной путь (написание этого поста заняло гораздо больше времени, чем реализация, я занимался этим примерно 30 минут)

Я написал функции, которые предварительно обрабатывают параметры запроса и добавляют групповой префикс для группировки определенных параметров.Затем я использую полученную карту Map[String, String] и продолжаю обработку с классом формы, выполняя проверку и т. д., как обычно. Это позволяет мне использовать в сопоставлении вложенные классы case и снизить ограничение в 18 параметров.

Осторожно: впереди уродливый код! Вероятно, мне не следует показывать такой ранний хакерский код, но я надеюсь, что это поможет кому-то еще, кто хочет найти обходной путь.

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 принимает префикс и заменяет его:

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

Когда у меня есть параметры в форме 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)

В своем действии я иду вперед и отфильтровываю каждая из моих групп

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

Наконец, я могу применить свою форму, как обычно, но теперь я получаю вложенную структуру I, которая уменьшает количество аргументов и, надеюсь, делает класс case более управляемым.

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

Используя этот подход, вы можете уменьшить количество параметров. Если ваши параметры не имеют того же префикса для простой группировки, что и моя проблема, вы все равно можете использовать тот же базовый подход, но фильтровать по другим критериям.

6
задан Magnus 14 June 2012 в 20:21
поделиться