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 })
私の戦略は、適用/適用解除の代わりにこの方法でマッピングを行い、ケース クラスの階層を作成することでした。その理由は、Case クラスでの 22 個の引数の制限を回避するためです。これは、私が遭遇した最初の一見恣意的な制限でした。最大 18 個の引数のマッピングが機能しますが、その後は長いコンパイル エラーが発生します。
エラーメッセージはここにあります (長すぎて含めることができません): https://gist.github.com/2928297
この制限を回避する方法についての提案を探しています。フォーム Post で 29 個のパラメーターを送信するのは悪い設計であることはわかっていますが、それでも可能であるはずです。
ハック/回避策/解決策
わかりました、これが私のハッキングされた回避策です(この投稿を書くのは実装よりもはるかに時間がかかりました、これについて〜30分間ハッキングしました)
リクエストパラメーターを前処理し、グループプレフィックスを追加して特定のパラメーターをグループ化する関数を作成しました。次に、結果の Map[String, String] を使用して、フォーム クラスの処理を続行し、通常どおり検証などを行います。これにより、マッピングでネストされたケース クラスを使用して、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 の形式のパラメーターがある場合、次のような形式でケース クラスをネストできます。
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 を取得することで、引数の数を減らし、ケース クラスをより管理しやすくすることができます。
clientRegistrationForm.bind(processedForm).fold( ... )
このアプローチを使用すると、パラメーターの数を抑えることができます。私の問題のように簡単にグループ化するためにパラメーターに同じプレフィックスがない場合でも、同じ基本的なアプローチを使用できますが、他の基準でフィルター処理できます。