尝试为models.DeviceContext实现我的第一个QueryStringBindable:
case class DeviceContext( deviceIdLike: String = "", deviceUseridLike: String = "")
我有util.Binders.scala如下:
package util
import play.api.mvc.QueryStringBindable
import models._
object Binders {
implicit def deviceContextBinder(implicit stringBinder: QueryStringBindable[String]) =
new QueryStringBindable[DeviceContext] {
override def bind(key: String, params: java.util.Map[String, Array[String]]): Option[Either[String, DeviceContext]] = {
Some({
val deviceIdLike = stringBinder.bind(key + ".deviceIdLike", params)
val deviceIUseridLike = stringBinder.bind(key + ".deviceUseridLike", params)
(deviceIdLike.isDefined && deviceIUseridLike.isDefined) match {
case true => Right(DeviceContext(deviceIdLike.get, deviceIUseridLike.get))
case false => Left("Unable to bind DeviceContext")
}
})
}
override def unbind(key: String, deviceContext: DeviceContext): String =
stringBinder.unbind(
key + ".deviceIdLike=" + deviceContext.deviceIdLike +
"&" + key + ".deviceUserIdLike=" + deviceContext.deviceUseridLike)
}
}
改编自documentation中的示例。我的build.sbt文件尝试使用以下命令使util.Binders可见:
import play.PlayImport.PlayKeys._
routesImport += "util.Binders._"
并且路线看起来像:
GET /device controllers.Devices.list(dc:models.DeviceContext)
然而,编译器并不满意:
[error] \ conf \ routes:76:找不到类型models.DeviceContext的QueryString binder。 尝试为此类型实现隐式QueryStringBindable。 [错误] GET / device controllers.Devices.list(deviceContext:DeviceContext)
[error] \ conf \ routes:76:方法隐含的参数不够:(隐式e:play.api.mvc.QueryStringBindable [models.DeviceContext])play.api.mvc.QueryStringBindable [models.DeviceContext]。 [错误]未指定的值参数e。
Scala版本为2.11.5,播放次数为2.3.9
import util.Binders
是显式导入,因此应包含在隐式搜索中。好像implicit def deviceContextBinder
的签名与所需的签名不匹配,但它返回了我的类型的QueryStringBindable,所以我不明白为什么它不匹配。
任何指示赞赏!
(旁注,文档使用params: Map[String,Seq[String]]
但是如果我使用它,编译器会抱怨它期待java.util.Map[String,Array[String]]
看起来很奇怪......请参阅下面的答案。)
编辑1 : 当我使用标准数据类型时,为了不调用我的客户QueryStringBindable,但是将代码留在项目中,编译器会报告新的错误,第一个错误是:
type arguments [String]不符合trait QueryStringBindable的类型参数bounds [T<:play.mvc.QueryStringBindable [T]]
答案 0 :(得分:2)
嗯,解决方案是我似乎必须将代码放在与case类相同的包中。当我这样做时,java.util.Map"解决方法"上面提到解决了,所以,删除Binders.scala并将DeviceContext.Scala扩展到以下工作:
package models
case class DeviceContext(deviceIdLike: String = "", deviceUseridLike: String = "")
object DeviceContext {
import play.api.mvc.QueryStringBindable
implicit def deviceContextBinder(implicit stringBinder: QueryStringBindable[String]) =
new QueryStringBindable[DeviceContext] {
override def bind(key: String, params: Map[String, Seq[String]]): Option[Either[String, DeviceContext]] = {
Some({
val deviceIdLike = stringBinder.bind(key + ".deviceIdLike", params)
val deviceIUseridLike = stringBinder.bind(key + ".deviceUseridLike", params)
(deviceIdLike, deviceIUseridLike) match {
case (Some(Right(di)), Some(Right(du))) => Right(DeviceContext(di, du))
case _ => Left("Unable to bind DeviceContext")
}
})
}
override def unbind(key: String, deviceContext: DeviceContext): String =
stringBinder.unbind(
key + ".deviceIdLike", deviceContext.deviceIdLike) +
"&" + stringBinder.unbind(key + ".deviceUserIdLike", deviceContext.deviceUseridLike)
}
}
如果我想在路径文件中以不合格的方式引用我的类型,即controllers.Devices.list(dc:DeviceContext)
,我还发现routesImports只需 。如果我愿意将参数写为dc:models.DeviceContext
,则不需要routesImports。
答案 1 :(得分:1)
而不是routesImport += "util.Binders"
尝试routesImport += "util.Binders._"
从对象中导入所有内容。
答案 2 :(得分:1)
在我的情况下,我在错误的伴侣对象中定义了QueryStringBindable。