2012-07-30 457 views
1

解决方案:我无法确定如何返回Option [User]的不存在,以便在未找到用户的情况下创建从控制器的虚拟用户对象和理由就可以了(感觉很糟糕,但这工作...): 从Application.scalaScala + Play - >类型不匹配;找到:anorm.RowParser必需:anorm.ResultSetParser [选项[models.User]]

val loginForm = Form(
tuple(
    "email" -> text, 
    "password" -> text 
) verifying ("Invalid email or password", result => result match { 
    case (email, password) => (User.authenticate(email, password).map{_.id}.getOrElse(0) != 0) 
}) 

,而不是:

val loginForm = Form(
    tuple(
    "email" -> text, 
    "password" -> text 
) verifying ("Invalid email or password", result => result match { 
    case (email, password) => User.authenticate(email, password).isDefined 
}) 

++++++++++++++++++ ORIGINAL 2 ++++++++++++++++++ 感谢您的建议!我做了一些改变,似乎越来越接近,但我无法弄清楚如何返回未命中的选项[用户]。我也试着情况_ =>空,见下文:

从User.scala

case class User(id: Int, email: String, name: String, password: String) 

object User { 

    // -- Parsers 

    /** 
    * Parse a User from a ResultSet 
    */ 
    val userParser = { 
      get[Option[Int]]("uid")~   
      get[Option[String]]("email")~ 
      get[Option[String]]("fname")~ 
      get[Option[String]]("pbkval") map { 
      case (uid~email~name~pbkval) => validate(uid,email, name, pbkval) 
      } 
    } 

    /** 
    * Retrieve a User from email. 
    */ 
    def findByEmail(email: String): Option[User] = { 
    DB.withConnection { implicit connection => 
     SQL("select * from get_pbkval({email})").on(
       'email -> email   
      ).as(userParser.singleOpt) 
    } 
    } 


    /** 
    * Authenticated user session start. 
    */ 
    def authenticate(email: String, password: String): Option[User] = { 
    DB.withConnection { implicit connection => 
     SQL(
      """ 
         select * from get_pbkval({email}) 
      """ 
      ).on(
       'email -> email 
      ).as(userParser.singleOpt) 

     } 
    } 

    /** 
    * Validate entry and create user object. 
    */ 
    def validate(uid: Option[Int], email: Option[String], fname: Option[String], pbkval: Option[String]): User = { 
       val uidInt : Int = uid.getOrElse(0) 
       val emailString: String = email.getOrElse(null) 
       val fnameString: String = fname.getOrElse(null) 
       val pbkvalString: String = pbkval.getOrElse(null) 
       User(uidInt, emailString, fnameString, pbkvalString) 
    } 

我想很明显,我没有真正得到的东西在这里根本..我已经通过http://www.playframework.org/modules/scala-0.9.1/anorm和阅读搜索了几个小时..任何帮助将不胜感激!

回答

3

您没有指定映射哪些行。在你的行映射器之后,放一个*来表示要映射哪些行。当你处理它时,我发现在单独的val中定义我的行映射器会更容易。像这样的东西。

val user = { 
    get[Option[Int]]("uid")~   
    get[Option[String]]("email")~ 
    get[Option[String]]("fname")~ 
    get[Option[String]]("pbkval") map { 
    case uid~email~name~password => validate(uid,email, name, password) 
    } 
} 

def authenticate(email: String, password: String): Option[User] = { 
DB.withConnection { implicit connection => 
    SQL(
    """ 
     select * from get_pbkval({email}) 
    """ 
    ).on(
     'email -> email 
    ).as(user *) 
    } 
} 

    def validate(uid: Option[Int], email: Option[String], fname: Option[String], pbkval: Option[String]): Option[User] = { 
    if (uid != None) { 
      val uidInt : Int = uid.getOrElse(0) 
      val emailString: String = email.getOrElse(null) 
      val fnameString: String = fname.getOrElse(null) 
      val pbkvalString: String = pbkval.getOrElse(null) 
      User(uidInt, emailString, fnameString, pbkvalString) 
    } else { return null} 
} 

注意“作为”方法现在有两个参数,你行映射器(这是目前定义为VAL“用户”和“*”代表着你要映射的所有行。

+0

感谢您的回复本,我已经做出了您建议的更改,感觉更接近 - 我现在得到这个错误:type mismatch; found:anorm.ResultSetParser [List [Option [models.User]]] required:anorm。 ResultSetParser [Option [models.User]] – bort 2012-07-31 08:26:48

+0

'''*'''表示你要返回一组用户,所以你可能想要修改返回类型,否则你会使用'''user.singleOpt'' ',但那么你的'''WHERE''子句可能是某种唯一的标识符(我会编辑答案,但是c不保证它会编译出来而不需要启动一个项目,我没有时间;-) – opyate 2012-07-31 13:32:08