背景
我正在尝试了解将隐式对象纳入 Scala 应用程序范围的最佳实践。
我有一个 Playframework 2.2.0 (Scala 2.10) web 应用程序,它混合了授权特征。它检查。Authenticated 对象检查范围内是否存在 user_id,尝试从缓存、数据库和 Web 服务调用中检索用户信息、访问令牌和称为 MagicNotebook 的数据包对象。如果请求有效,则将各种对象添加到包装的请求中。
object Authenticated extends ActionBuilder[AuthenticatedRequest] {
def invokeBlock[A](request: Request[A],
block: (AuthenticatedRequest[A] => Future[SimpleResult])) = {
request.session.get(userName).map { implicit userId =>
Cache.getAs[DbUser](userKey).map { user =>
Cache.getAs[String](accessTokenKey).map { accessToken =>
Cache.getAs[MagicNotebook](magicNotebookKey(userId)).map { notebook =>
block(AuthenticatedRequest(user, accessToken, notebook, request) )
}.getOrElse(startOver)
}.getOrElse {
requestNewAccessToken(user.token).flatMap { response =>
persistAccessToken(response).map { accessToken =>
Cache.getAs[MagicNotebook](magicNotebookKey(userId)).map { notebook =>
block(AuthenticatedRequest(user, accessToken, notebook, request))
}.getOrElse(startOver)
}.getOrElse(startOver)
}
}
}.getOrElse(startOver) // user not found in Cache
}.getOrElse(startOver) // userName not found in session
}
}
}
case class AuthenticatedRequest[A](user: DbUser,
accessToken: String,
magic: MagicNotebook,
request: Request[A])
extends WrappedRequest[A](request)
问题
将这些隐式变量带入范围的最佳方法是什么?
通过隐式类?
我尝试使用隐式伴随类,代码如下:
object Helper {
implicit class Magical(request: AuthenticatedRequest[AnyContent]) {
def folderMap = request.magic.fMap
def documentMap = request.magic.dMap
}
}
但是,我并没有真正从这种方式中获得隐含的好处:
def testing = Authenticated { implicit request =>
import services.Helper._
request.magic.home.folders // doesn't compile
request.magic.home.folders(Magical(request).ffMap) // compiles, but not implicitly
Ok("testing 123")
}
通过导入声明?
我考虑的一种可能性是通过控制器中的导入语句。在这里,请求MagicNotebook
在范围内有一个对象,我想将其用作隐式变量。
def testing = Authenticated { implicit request =>
import request.magic._
request.magic.home.folders // implicit map is a parameter to the `folder` method
Ok("testing 123")
}
通过伴侣特质?
在这里,我创建了一个伴随特征,该特征混合到Authenticate
特征中,该特征包括MagicNotebook
对象的两个映射到控制器范围内。
trait Magic {
implicit def folderMap[A](implicit request: AuthenticatedRequest[A]) =
request.magic.fMap
implicit def docMap[A](implicit request: AuthenticatedRequest[A]) =
request.magic.dMap
}
我的偏好是伴侣特征解决方案,但我想知道是否有更好的方法被我忽略了。我最终重写了使用隐式变量的方法,使用 的MagicNotebook
两个映射而不是整个对象作为隐式参数。
但同样,我想知道是否有更好的方法。