Scala 和 Play:如何使用我的隐式对象?
Scala and Play: how can I use my implicit object?
隐式参数应该很容易,但到目前为止还不是。
我一直在使用 ReactiveMongo 在我的 Scala / Play 2.4 应用程序中保存和检索数据。有一段时间,我一直在我的 Controller 中进行保存,但我想将代码移动到正在保存的实体的伴随对象中。这就是麻烦开始的地方。
这是我的控制器的相关部分,展示了 是如何工作的:
package controllers
...
import model.Destination
import model.Destination.DestinationBSONReader
import scala.concurrent.ExecutionContext.Implicits.global
...
def add = Action { implicit request =>
Destination.destinationForm().bindFromRequest.fold(
formWithErrors => {
implicit val helper = sfh(formWithErrors)
BadRequest(views.html.addDestination(formWithErrors))
},
destinationData => {
Destination.mongoCollection.insert(destinationData)
...
Redirect("/destinations").flashing("success" -> s"The destination ${destinationData.name} has been created")
}
}
)
}
您可以想象提交的表单包含填充 "Destination" 的数据,然后将其保存到 Mongo。 Destination 对象被导入,Scala ExecutionContext 也是如此。我的 "Destination" 伴随对象有一个 BSONDocumentWriter[Destination] 的实例(mongoCollection.insert() 调用隐式需要它),如下所示:
object Destination {
...
implicit object DestinationBSONWriter extends BSONDocumentWriter[Destination] {
override def write(destination: Destination): BSONDocument = {
val dbId = if (destination.id.isDefined) { destination.id.get } else { BSONObjectID.generate.stringify }
destination.newId = dbId
BSONDocument(
"id" -> dbId,
... lots of other key/value pairs,
"name" -> destination.name)
}
}
...
}
现在,我想将 mongoCollection.insert(destinationData) 调用移动到同一个 "Destination" 对象;控制器真的不应该与数据存储交谈。所以我创建了一个简单的方法,无论我做什么都会导致编译错误:
def create(destination: Destination) = {
Destination.mongoCollection.insert(destination)
}
^- 编译失败; "could not find implicit value for parameter writer: reactivemongo.bson.BSONDocumentWriter[model.Destination]"
所以我在 class 的顶部添加了导入,因为 Scala 编译器应该在搜索隐式时查看导入:
import model.Destination.DestinationBSONWriter
import scala.concurrent.ExecutionContext.Implicits.global
^-同样的编译错误
所以我决定显式传递隐式参数:
def create(destination: Destination) = {
Destination.mongoCollection.insert(destination)(writer = DestinationBSONWriter, ec=global)
}
^- 那个导致编译器挂起,我需要重新启动激活器。
我很困惑。该隐式参数 就在同一对象中 ,但编译器未检测到它。我该如何使用它?
经过一天的调查,SBT 显然存在问题。无论出于何种原因,它决定在应该成功编译我的代码时挂起。
隐式参数应该很容易,但到目前为止还不是。
我一直在使用 ReactiveMongo 在我的 Scala / Play 2.4 应用程序中保存和检索数据。有一段时间,我一直在我的 Controller 中进行保存,但我想将代码移动到正在保存的实体的伴随对象中。这就是麻烦开始的地方。
这是我的控制器的相关部分,展示了 是如何工作的:
package controllers
...
import model.Destination
import model.Destination.DestinationBSONReader
import scala.concurrent.ExecutionContext.Implicits.global
...
def add = Action { implicit request =>
Destination.destinationForm().bindFromRequest.fold(
formWithErrors => {
implicit val helper = sfh(formWithErrors)
BadRequest(views.html.addDestination(formWithErrors))
},
destinationData => {
Destination.mongoCollection.insert(destinationData)
...
Redirect("/destinations").flashing("success" -> s"The destination ${destinationData.name} has been created")
}
}
)
}
您可以想象提交的表单包含填充 "Destination" 的数据,然后将其保存到 Mongo。 Destination 对象被导入,Scala ExecutionContext 也是如此。我的 "Destination" 伴随对象有一个 BSONDocumentWriter[Destination] 的实例(mongoCollection.insert() 调用隐式需要它),如下所示:
object Destination {
...
implicit object DestinationBSONWriter extends BSONDocumentWriter[Destination] {
override def write(destination: Destination): BSONDocument = {
val dbId = if (destination.id.isDefined) { destination.id.get } else { BSONObjectID.generate.stringify }
destination.newId = dbId
BSONDocument(
"id" -> dbId,
... lots of other key/value pairs,
"name" -> destination.name)
}
}
...
}
现在,我想将 mongoCollection.insert(destinationData) 调用移动到同一个 "Destination" 对象;控制器真的不应该与数据存储交谈。所以我创建了一个简单的方法,无论我做什么都会导致编译错误:
def create(destination: Destination) = {
Destination.mongoCollection.insert(destination)
}
^- 编译失败; "could not find implicit value for parameter writer: reactivemongo.bson.BSONDocumentWriter[model.Destination]"
所以我在 class 的顶部添加了导入,因为 Scala 编译器应该在搜索隐式时查看导入:
import model.Destination.DestinationBSONWriter
import scala.concurrent.ExecutionContext.Implicits.global
^-同样的编译错误
所以我决定显式传递隐式参数:
def create(destination: Destination) = {
Destination.mongoCollection.insert(destination)(writer = DestinationBSONWriter, ec=global)
}
^- 那个导致编译器挂起,我需要重新启动激活器。
我很困惑。该隐式参数 就在同一对象中 ,但编译器未检测到它。我该如何使用它?
经过一天的调查,SBT 显然存在问题。无论出于何种原因,它决定在应该成功编译我的代码时挂起。