scalaslick-2.0

Slick select using value object (extending AnyVal)


I am using Slick 2.1.0 with Scala 2.10. I have a value object (EMail) that I map to a VARCHAR column.

object EMail {
  import java.util.regex.Pattern
  val emailRegex = Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE)

  val empty = EMail("x@y.com")
}

case class EMail(value: String) extends AnyVal with MappedTo[String] {
  def isValid: Boolean = EMail.emailRegex.matcher(value).find

  def validate: EMail = {
    assert(isValid)
    EMail(value.trim.toLowerCase)
  }

  override def toString = validate.value
}

The Column definition is:

def email = column[Option[EMail]]("email_address")

This is my attempt at writing a finder:

def findByEmail(email: Option[EMail]): Option[User] =
  database.withSession { implicit session: Session =>
    queryAll.filter(e => e.email.isDefined && e.email === email).firstOption
  }

This is the error message I get:

[error] Users.scala:52: ambiguous implicit values: [error] both value BooleanCanBeQueryCondition in object CanBeQueryCondition of type => scala.slick.lifted.CanBeQueryCondition[Boolean] [error] and value BooleanOptionColumnCanBeQueryCondition in object CanBeQueryCondition of type => scala.slick.lifted.CanBeQueryCondition[scala.slick.lifted.Column[Option[Boolean]]] [error] match expected type scala.slick.lifted.CanBeQueryCondition[Nothing] [error] queryAll.filter(_.email === email.map(_.value)).firstOption [error] ^


Solution

  • You don't have to pass an Option[EMail] to your method, you could simply make:

    def findByEmail(email: EMail): Option[User] = {
      database.withSession { implicit session =>
        queryAll.filter(_.email === email).firstOption
      }
    }
    

    If you really need an Option[EMail]] as the input parameter, you should try the following:

    def findByEmail(emailOpt: Option[EMail]): Option[User] = {
      emailOpt.flatMap { email =>
        database.withSession { implicit session =>
          queryAll.filter(_.email === email).firstOption
        }
      }
    }