Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala Type Erasure on case classes how to solve

Tags:

scala

implicit

I have a trait and two case classes that extends it:

trait Authenticatable {
  val email: String
  val pass: String
  val id: Long
  val sessionid: String
}

case class Admin(
  id: Long,
  email: String,
  pass: String,
  sessionid: Option[String] = None) extends Authenticatable

case class Client(
  id: Long,
  email: String,
  pass: String,
  sessionid: Option[String] = None) extends Authenticatable

And I have functions witch should authenticate user, make copy of object with new sessionid and return it.

  def auth(email: String, password: String): Try[Admin] ={
    checkPass(models.Admin.findBy(sqls"email = $email"), password)
  }

  def auth(email: String, password: String, customer: Customer): Try[Customer] ={
    checkPass(models.Customer.findBy(sqls"email = $email"), password)
  }

  private def checkPass (model: Option[Authenticatable], password: String): Try[Authenticatable]={
    model match {
      case Some(m) => check(password, m.pass).map(_ => m)
      case _ => Failure(new Exception("Authentication failure!"))
    }
  }

The problem is: I can't make copy of object in auth function because function checkPass returns Authenticatable and not Client or Admin class and Authenticatable doesn't have copy method of case classes.

What is the right way to solve this problem?

like image 909
sergeda Avatar asked Dec 18 '25 04:12

sergeda


1 Answers

If you use type parameters, you can avoid throwing away the information that checkPass will always return the same type of Authenticable as was given to it:

private def checkPass[A <: Authenticatable](model: Option[A], password: String): Try[A] =
  // exactly the same body here

This means that in auth you can have e.g.:

def auth(email: String, password: String): Try[Admin] =
  checkPass(models.Admin.findBy(sqls"email = $email"), password)
    .map(_.copy(sessionid = Some("whatever")))
like image 168
Hugh Avatar answered Dec 20 '25 23:12

Hugh