Play无法在单独的程序包

时间:2015-08-07 08:30:13

标签: scala playframework-2.3

尝试为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]]

3 个答案:

答案 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。