Scala Play 2.5表单bindFromRequest:在这里找不到任何HTTP请求?

时间:2016-12-11 20:42:40

标签: scala playframework deadbolt-2

我有一个像这样实现的控制器动作:

def doChangePassword = deadbolt.Restrict(List(Array(Application.USER_ROLE_KEY)))() 
{ request => // <<<<<<<<<<<< here is the request 
  Future {
    val context = JavaHelpers.createJavaContext(request)
    com.feth.play.module.pa.controllers.AuthenticateBase.noCache(context.response())

    val filledForm = Account.PasswordChangeForm.bindFromRequest
    // compilation error here, it can't see the request ^^^^^^^

    if (filledForm.hasErrors) {
      // User did not select whether to link or not link
      BadRequest(views.html.account.password_change(userService, filledForm))
    } else {
      val Some(user: UserRow) = userService.getUser(context.session)
      val newPassword = filledForm.get.password
      userService.changePassword(user, new MyUsernamePasswordAuthUser(newPassword), true)
      Redirect(routes.Application.profile).flashing(
        Application.FLASH_MESSAGE_KEY -> messagesApi.preferred(request)("playauthenticate.change_password.success")
      )
    }
  }
}

上面的实现会导致编译错误:

[error] /home/bravegag/code/play-authenticate-usage-scala/app/controllers/Account.scala:74: Cannot find any HTTP Request here
[error]         val filledForm =  Account.PasswordChangeForm.bindFromRequest
[error]                                                     ^
[error] one error found

但是,如果我改变第2行:

{ request => // <<<<<<<<<<<< here is the request 

{ implicit request => // <<<<<<<<<<<< here is the request 

然后它编译......但为什么?

2 个答案:

答案 0 :(得分:8)

您要找的是Implicit Parameters。简而言之:

隐式参数可以像常规或显式参数一样传递。如果您没有显式提供隐式参数,编译器将尝试为您传递一个。隐含可以来自各个地方。来自常见问题Where does Scala look for implicits?

  
      
  1. 首先查看当前范围      
        
    • 当前范围中定义的隐含
    •   
    • 明确导入
    •   
    • 通配符导入
    •   
  2.   
  3. 现在查看相关类型      
        
    • 类型的伴随对象
    •   
    • 参数类型的隐含范围(2.9.1)
    •   
    • 类型参数的隐含范围(2.8.0)
    •   
    • 嵌套类型的外部对象
    •   
    • 其他尺寸
    •   
  4.   

数字1下的隐含优先于数字2下的数据。

在示例中将request标记为implicit,即表示“在当前范围内定义了隐式”。您需要有一个隐式请求,因为bindFormRequest“要求”您传递一个请求。见其签名:

bindFromRequest()(implicit request: Request[_]): Form[T]

现在您在范围内有implicit request,编译器会自动将其传递给bindFormRequerst

正如我在开头提到的那样,你也可以明确地传递request

val filledForm = Account.PasswordChangeForm.bindFromRequest()(request)

在后一种情况下,您无需将request声明为implicit,因为您显然明确地传递了request。两种变体都是平等的。这取决于你喜欢哪一个。

答案 1 :(得分:2)