如何使用 Scala 在路由上绑定枚举?
How to bind enum on routes using scala?
我正在尝试接收一些过滤器列表作为 get 请求的查询参数,这也是我控制器上的一个枚举。为此,我在 scala 中使用了 play 框架。问题是:我无法将枚举类型作为查询参数放在上面,因为 IDE 无法识别为有效类型。
所以,我在路由文件中有这样的东西
GET /service-orders/ controllers.ServiceOrdersController.listServiceOrders(status: ServiceStatus)
我的枚举文件:
object ServiceStatus extends Enumeration {
type ServiceStatus = Value
val Pending = Value("pending")
val Started = Value("started")
val Completed = Value("completed")
val Error = Value("error")
}
在 build.sbt 上,我使用它试图在路由文件中注入包
routesImport ++= Seq(
"serviceOrders.models.ServiceStatus"
),
我尝试了很多东西,但都没有成功。我在某个地方读到我可以使用 QueryStringBindable
函数,但是我做的不太好......你们能帮我解决这个问题吗?
编辑: 顺便说一句,有一种方法可以在不执行此操作的情况下检查状态是否包含在过滤器列表中?
.filter {
serviceOrder =>
status.map(serviceOrder.serviceStatus === _)
.reduceOption(_ || _)
.getOrElse(true: Rep[Boolean])
}
这是我能想到的通过从 API.
作为查询参数接收的过滤器列表来过滤状态的唯一方法
您可以像这样实现 QueryStringBindable
实例:
package serviceOrders.models
object ServiceStatus extends Enumeration {
type ServiceStatus = Value
val Pending = Value("pending")
val Started = Value("started")
val Completed = Value("completed")
val Error = Value("error")
implicit val queryStringBindable: QueryStringBindable[ServiceStatus] =
new QueryStringBindable[ServiceStatus] {
override def bind(
key: String,
params: Map[String, Seq[String]]
): Option[Either[String, ServiceStatus]] =
params.get(key).collect {
case Seq(s) =>
ServiceStatus.values.find(_.toString == s).toRight("invalid value")
}
override def unbind(key: String, value: ServiceStatus): String =
implicitly[QueryStringBindable[String]].unbind(key, value.toString)
}
}
在 build.sbt 你需要这个:
routesImport ++= Seq("serviceOrders.models.ServiceStatus._")
这在你的路线文件中:
GET /some/route controllers.SomeController.index(status: ServiceStatus)
然后您可以创建一个 index
方法,该方法在 SomeController
中采用 ServiceStatus
参数,Play 将处理查询参数。
// 编辑:
您实际上可以使用 QueryStringBindable.Parsing
class 来进一步简化实现。
我正在尝试接收一些过滤器列表作为 get 请求的查询参数,这也是我控制器上的一个枚举。为此,我在 scala 中使用了 play 框架。问题是:我无法将枚举类型作为查询参数放在上面,因为 IDE 无法识别为有效类型。
所以,我在路由文件中有这样的东西
GET /service-orders/ controllers.ServiceOrdersController.listServiceOrders(status: ServiceStatus)
我的枚举文件:
object ServiceStatus extends Enumeration {
type ServiceStatus = Value
val Pending = Value("pending")
val Started = Value("started")
val Completed = Value("completed")
val Error = Value("error")
}
在 build.sbt 上,我使用它试图在路由文件中注入包
routesImport ++= Seq(
"serviceOrders.models.ServiceStatus"
),
我尝试了很多东西,但都没有成功。我在某个地方读到我可以使用 QueryStringBindable
函数,但是我做的不太好......你们能帮我解决这个问题吗?
编辑: 顺便说一句,有一种方法可以在不执行此操作的情况下检查状态是否包含在过滤器列表中?
.filter {
serviceOrder =>
status.map(serviceOrder.serviceStatus === _)
.reduceOption(_ || _)
.getOrElse(true: Rep[Boolean])
}
这是我能想到的通过从 API.
作为查询参数接收的过滤器列表来过滤状态的唯一方法您可以像这样实现 QueryStringBindable
实例:
package serviceOrders.models
object ServiceStatus extends Enumeration {
type ServiceStatus = Value
val Pending = Value("pending")
val Started = Value("started")
val Completed = Value("completed")
val Error = Value("error")
implicit val queryStringBindable: QueryStringBindable[ServiceStatus] =
new QueryStringBindable[ServiceStatus] {
override def bind(
key: String,
params: Map[String, Seq[String]]
): Option[Either[String, ServiceStatus]] =
params.get(key).collect {
case Seq(s) =>
ServiceStatus.values.find(_.toString == s).toRight("invalid value")
}
override def unbind(key: String, value: ServiceStatus): String =
implicitly[QueryStringBindable[String]].unbind(key, value.toString)
}
}
在 build.sbt 你需要这个:
routesImport ++= Seq("serviceOrders.models.ServiceStatus._")
这在你的路线文件中:
GET /some/route controllers.SomeController.index(status: ServiceStatus)
然后您可以创建一个 index
方法,该方法在 SomeController
中采用 ServiceStatus
参数,Play 将处理查询参数。
// 编辑:
您实际上可以使用 QueryStringBindable.Parsing
class 来进一步简化实现。