Reputation: 13
SOLUTION: I could not figure our how to return the non-exists for of Option[User] so in the case of not user found I create a dummy user object and reason on it from the controller (feels awful but working...): from Application.scala
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)
})
)
AS OPPOSED TO:
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 ++++++++++++++++++ Thanks for the advice! I have made some change and seem to be getting closer however I can't figure out how to return an undefinded Option[user]. I have also tried case _ => null, See below:
From 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)
}
I guess it is clear that I am not really getting something fundamental here.. I have read through http://www.playframework.org/modules/scala-0.9.1/anorm and searched around for hours.. any help would be much appreciated!
Upvotes: 1
Views: 3291
Reputation: 379
You didn't specify which rows to map. After your row mapper, put a * to signify which rows to map. While you're at it, I find it easier to define my row mapper in a separate val. Something like this.
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}
}
Note the "as" method now has two arguments, your row mapper (which is now defined as a val "user", and a "*" signifying that you want to map all of the rows.
Upvotes: 3