0

Assume these two simple queries:

def findById(id: Long): Option[Account] = database.withSession { implicit s: Session =>
  val query = for (a <- Accounts if a.id === id) yield a.*
  query.list.headOption
}

def findByUID(uid: String): Option[Account] = database.withSession { implicit s: Session =>
  val query = for (a <- Accounts if a.uid === uid) yield a.*
  query.list.headOption
}

I would like to rewrite it to remove the boilerplate duplication to something like this:

def findBy(criteria: ??? => Boolean): Option[Account] = database.withSession {
  implicit s: Session =>
    val query = for (a <- Accounts if criteria(a)) yield a.*
    query.list.headOption
}

def findById(id: Long) = findBy(_.id === id)

def findByUID(uid: Long) = findBy(_.uid === uid)

I don't know how to achieve it for there are several implicit conversions involved in the for comprehension I haven't untangled yet. More specifically: what would be the type of ??? => Boolean in the findBy method?

EDIT

These are Account and Accounts classes:

case class Account(id: Option[Long], uid: String, nick: String)

object Accounts extends Table[Account]("account") {
  def id = column[Option[Long]]("id")
  def uid = column[String]("uid")
  def nick = column[String]("nick")
  def * = id.? ~ uid ~ nick <> (Account, Account.unapply _)
}
Karel Smutný
  • 1,100
  • 1
  • 9
  • 17
  • Please see the answer at http://stackoverflow.com/questions/14501159/higher-order-functions-with-scala-slick-for-dry-goodness/16892497#16892497 – Sameer Jun 12 '13 at 07:27

1 Answers1

4

I have this helper Table:

abstract class MyTable[T](_schemaName: Option[String], _tableName: String) extends Table[T](_schemaName, _tableName) {
  import scala.slick.lifted._
  def equalBy[B: BaseTypeMapper]
    (proj:this.type => Column[B]):B => Query[this.type,T] = { (str:B) => 
     Query[this.type,T,this.type](this) where { x => proj(x) === str} }

}

Now you can do:

 val q=someTable.equalBy(_.someColumn) 
 q(someValue)
virtualeyes
  • 11,147
  • 6
  • 56
  • 91
pedrofurla
  • 12,763
  • 1
  • 38
  • 49
  • 2
    +1, nice solution, however, how does this differ from createFinderBy? The same functionality is built into Slick with Foo.createFinderBy(_.whatever) – virtualeyes Jan 15 '13 at 14:00
  • Not exactly. createFinder is different because it creates a QueryTemplate and you can add other restrictions in it. I invented this one exactly to overcome this limitation from createFinder. – pedrofurla Jan 15 '13 at 16:21
  • Oh, I forgot to remove the semicolon after making the one liner into multi lines. – pedrofurla Jan 15 '13 at 16:23
  • Above, I mean that QueryTemplate can't have additional restrictions added – pedrofurla Jan 15 '13 at 18:43
  • Will try out when I switch from ScalaQuery to Slick, might come in handy...thanks – virtualeyes Jan 15 '13 at 20:29