[Stack Overflow] Play 和 Scala 的 mapping 内容有数量限制吗?
原文:http://stackoverflow.com/questions/11869990/mapping-error-with-the-play-frameworks-form
0down votefavorite
我在使用 Play! framework 里的 mapping 时候遇到了问题。由于把mapping的参数改成一个的时候它运行的很好,所以我怀疑当我的mapping里的参数数量太大的时候他就罢工了,可是我在它的文档里没有找到任何关于这件事的内容:http://www.playframework.org/documentation/api/2.0.2/scala/index.html#play.api.data.Form
这是我的form的代码:
val paymentForm: Form[PaymentValues] = Form(// Define a mapping that will handle User valuesmapping( "message" -> text, "x_card_num" -> text, "x_exp_date" -> text, "exp_year" -> text, "exp_month" -> text, "x_card_code" -> text, "x_first_name" -> text, "x_last_name" -> text, "x_address" -> text, "x_city" -> text, "x_state" -> text, "x_zip" -> text, "save_account" -> text, "product_array" -> text, "x_amount" -> text, "products_json" -> text, "auth_net_customer_profile_id" -> text, "auth_net_payment_profile_id" -> text, "customer_id" -> text, "saved_payments_object" -> text )(PaymentValues.apply)(PaymentValues.unapply))
有没有什么方法可以把mapping分开吗?求教育。
下面是报错:
! Internal server error, for request [GET /] ->sbt.PlayExceptions$CompilationException: Compilation error [Overloaded method value [mapping] cannot be applied to ((java.lang.String, play.api.data.Mapping[String]), (java.lang.String, play.api.data.Mapping[String]), (java.lang.String, play.api.data.Mapping[String]), (java.lang.String, play.api.data.Mapping[String]), (java.lang.String, play.api.data.Mapping[String]), (java.lang.String, play.api.data.Mapping[String]), (java.lang.String, play.api.data.Mapping[String]), (java.lang.String, play.api.data.Mapping[String]), (java.lang.String, play.api.data.Mapping[String]), (java.lang.String, play.api.data.Mapping[String]), (java.lang.String, play.api.data.Mapping[String]), (java.lang.String, play.api.data.Mapping[String]), (java.lang.String, play.api.data.Mapping[String]), (java.lang.String, play.api.data.Mapping[String]), (java.lang.String, play.api.data.Mapping[String]), (java.lang.String, play.api.data.Mapping[String]), (java.lang.String, play.api.data.Mapping[String]), (java.lang.String, play.api.data.Mapping[String]), (java.lang.String, play.api.data.Mapping[String]), (java.lang.String, play.api.data.Mapping[String]))]at sbt.PlayReloader$$anon$2$$anonfun$reload$3$$anonfun$2$$anonfun$apply$11$$anonfun$apply$12.apply(PlayReloader.scala:224) ~[na:na]at sbt.PlayReloader$$anon$2$$anonfun$reload$3$$anonfun$2$$anonfun$apply$11$$anonfun$apply$12.apply(PlayReloader.scala:224) ~[na:na]at scala.Option.map(Option.scala:133) ~[scala-library.jar:0.11.2]at sbt.PlayReloader$$anon$2$$anonfun$reload$3$$anonfun$2$$anonfun$apply$11.apply(PlayReloader.scala:224) ~[na:na]at sbt.PlayReloader$$anon$2$$anonfun$reload$3$$anonfun$2$$anonfun$apply$11.apply(PlayReloader.scala:221) ~[na:na]at scala.Option.map(Option.scala:133) ~[scala-library.jar:0.11.2]
这里是参数的定义:
package models// definition of PaymentValuescase class PaymentValues( message: String, x_card_num: String, x_exp_date: String, exp_year: String, exp_month: String, x_card_code: String, x_first_name: String, x_last_name: String, x_address: String, x_city: String, x_state: String, x_zip: String, save_account: String, product_array: String, x_amount: String, products_json: String, auth_net_customer_profile_id: String, auth_net_payment_profile_id: String, customer_id: String, saved_payments_object: String)
forms scala playframework mapping playframework-2.0share|improve this questionedited Aug 10 '12 at 10:34case class
. If so, could you drop it in the question please? Because the problem should come from there. thanks – andy petrella Aug 8 '12 at 21:30 Hey Andy, I just updated with its definition. Thanks. – user687245 Aug 8 '12 at 23:043 Why not just do the refactor recommended here? stackoverflow.com/questions/11654992/… – Brian SmithAug 9 '12 at 14:561 Brian is right, you will probably need to refactor as the Form mapping API has a hard limit of 18 parameters (for reasons much like in Brian's link) – thatsmydoing Aug 9 '12 at 16:26可以细读一下文档接口,Scala 和 Play 对 mapping 都是有参数数量限制的。
事实上,Play 用一个定义了数据绑定的类 ObjectMapping
代替了 mapping 。这个 ObjectMapping
类可以应用 apply 和 unapply 方法, domain object (对于 unapply来说) 和其他 20 多个参数组成构造参数。一共23个。
Scala 把所有的抽象类型 (tuples, functions, case classes, ...)的参数都限制在了22个 (看这里有证据)
这就是为什么Play不支持一个包含20个参数的mapping... (事实上据大量的留言说当有18个参数的时候他就不行了)
第二次编辑
如果你不相信我... 试试这个 ^^
import play.api.data._ import validation._import format._def mapping[R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20](a1: (String, Mapping[A1]), a2: (String, Mapping[A2]), a3: (String, Mapping[A3]), a4: (String, Mapping[A4]), a5: (String, Mapping[A5]), a6: (String, Mapping[A6]), a7: (String, Mapping[A7]), a8: (String, Mapping[A8]), a9: (String, Mapping[A9]), a10: (String, Mapping[A10]), a11: (String, Mapping[A11]), a12: (String, Mapping[A12]), a13: (String, Mapping[A13]), a14: (String, Mapping[A14]), a15: (String, Mapping[A15]), a16: (String, Mapping[A16]), a17: (String, Mapping[A17]), a18: (String, Mapping[A18]), a19: (String, Mapping[A19]), a20: (String, Mapping[A20]))(apply: Function18[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, R])(unapply: Function1[R, Option[(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20)]]): Mapping[R] = { ObjectMapping20(apply, unapply, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)}case class ObjectMapping20[R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20](apply: Function20[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, R], unapply: Function1[R, Option[(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20)]], f1: (String, Mapping[A1]), f2: (String, Mapping[A2]), f3: (String, Mapping[A3]), f4: (String, Mapping[A4]), f5: (String, Mapping[A5]), f6: (String, Mapping[A6]), f7: (String, Mapping[A7]), f8: (String, Mapping[A8]), f9: (String, Mapping[A9]), f10: (String, Mapping[A10]), f11: (String, Mapping[A11]), f12: (String, Mapping[A12]), f13: (String, Mapping[A13]), f14: (String, Mapping[A14]), f15: (String, Mapping[A15]), f16: (String, Mapping[A16]), f17: (String, Mapping[A17]), f18: (String, Mapping[A18]), f19: (String, Mapping[A19]), f20: (String, Mapping[A20]), val key: String = "", val constraints: Seq[Constraint[R]] = Nil) extends Mapping[R] with ObjectMapping { val field1 = f1._2.withPrefix(f1._1).withPrefix(key) val field2 = f2._2.withPrefix(f2._1).withPrefix(key) val field3 = f3._2.withPrefix(f3._1).withPrefix(key) val field4 = f4._2.withPrefix(f4._1).withPrefix(key) val field5 = f5._2.withPrefix(f5._1).withPrefix(key) val field6 = f6._2.withPrefix(f6._1).withPrefix(key) val field7 = f7._2.withPrefix(f7._1).withPrefix(key) val field8 = f8._2.withPrefix(f8._1).withPrefix(key) val field9 = f9._2.withPrefix(f9._1).withPrefix(key) val field10 = f10._2.withPrefix(f10._1).withPrefix(key) val field11 = f11._2.withPrefix(f11._1).withPrefix(key) val field12 = f12._2.withPrefix(f12._1).withPrefix(key) val field13 = f13._2.withPrefix(f13._1).withPrefix(key) val field14 = f14._2.withPrefix(f14._1).withPrefix(key) val field15 = f15._2.withPrefix(f15._1).withPrefix(key) val field16 = f16._2.withPrefix(f16._1).withPrefix(key) val field17 = f17._2.withPrefix(f17._1).withPrefix(key) val field18 = f18._2.withPrefix(f18._1).withPrefix(key) val field19 = f19._2.withPrefix(f19._1).withPrefix(key) val field20 = f20._2.withPrefix(f20._1).withPrefix(key) def bind(data: Map[String, String]): Either[Seq[FormError], R] = { merge(field1.bind(data), field2.bind(data), field3.bind(data), field4.bind(data), field5.bind(data), field6.bind(data), field7.bind(data), field8.bind(data), field9.bind(data), field10.bind(data), field11.bind(data), field12.bind(data), field13.bind(data), field14.bind(data), field15.bind(data), field16.bind(data), field17.bind(data), field18.bind(data), field19.bind(data), field20.bind(data)) match { case Left(errors) => Left(errors) case Right(values) => { applyConstraints(apply( values(0).asInstanceOf[A1], values(1).asInstanceOf[A2], values(2).asInstanceOf[A3], values(3).asInstanceOf[A4], values(4).asInstanceOf[A5], values(5).asInstanceOf[A6], values(6).asInstanceOf[A7], values(7).asInstanceOf[A8], values(8).asInstanceOf[A9], values(9).asInstanceOf[A10], values(10).asInstanceOf[A11], values(11).asInstanceOf[A12], values(12).asInstanceOf[A13], values(13).asInstanceOf[A14], values(14).asInstanceOf[A15], values(15).asInstanceOf[A16], values(16).asInstanceOf[A17], values(17).asInstanceOf[A18], values(18).asInstanceOf[A19], values(19).asInstanceOf[A20])) } } } def unbind(value: R): (Map[String, String], Seq[FormError]) = { unapply(value).map { fields => val (v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) = fields val a1 = field1.unbind(v1) val a2 = field2.unbind(v2) val a3 = field3.unbind(v3) val a4 = field4.unbind(v4) val a5 = field5.unbind(v5) val a6 = field6.unbind(v6) val a7 = field7.unbind(v7) val a8 = field8.unbind(v8) val a9 = field9.unbind(v9) val a10 = field10.unbind(v10) val a11 = field11.unbind(v11) val a12 = field12.unbind(v12) val a13 = field13.unbind(v13) val a14 = field14.unbind(v14) val a15 = field15.unbind(v15) val a16 = field16.unbind(v16) val a17 = field17.unbind(v17) val a18 = field18.unbind(v18) val a19 = field19.unbind(v19) val a20 = field20.unbind(v20) (a1._1 ++ a2._1 ++ a3._1 ++ a4._1 ++ a5._1 ++ a6._1 ++ a7._1 ++ a8._1 ++ a9._1 ++ a10._1 ++ a11._1 ++ a12._1 ++ a13._1 ++ a14._1 ++ a15._1 ++ a16._1 ++ a17._1 ++ a18._1 ++ a19._1 ++ a20._1) -> (a1._2 ++ a2._2 ++ a3._2 ++ a4._2 ++ a5._2 ++ a6._2 ++ a7._2 ++ a8._2 ++ a9._2 ++ a10._2 ++ a11._2 ++ a12._2 ++ a13._2 ++ a14._2 ++ a15._2 ++ a16._2 ++ a17._2 ++ a18._2 ++ a19._2 ++ a20._2) }.getOrElse(Map.empty -> Seq(FormError(key, "unbind.failed"))) } def withPrefix(prefix: String): ObjectMapping20[R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20] = addPrefix(prefix).map(newKey => this.copy(key = newKey)).getOrElse(this) def verifying(addConstraints: Constraint[R]*): ObjectMapping20[R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20] = { this.copy(constraints = constraints ++ addConstraints.toSeq) } val mappings = Seq(this) ++ field1.mappings ++ field2.mappings ++ field3.mappings ++ field4.mappings ++ field5.mappings ++ field6.mappings ++ field7.mappings ++ field8.mappings ++ field9.mappings ++ field10.mappings ++ field11.mappings ++ field12.mappings ++ field13.mappings ++ field14.mappings ++ field15.mappings ++ field16.mappings ++ field17.mappings ++ field18.mappings ++ field19.mappings ++ field20.mappings}
share|improve this answeredited Aug 9 '12 at 20:20