Alex Naspo
Alex Naspo

Reputation: 2102

scala-cass generic read from cassandra table as case class

I am attempting to use scala-cass in order to read from cassandra and convert the resultset to a case class using resultSet.as[CaseClass]. This works great when running the following.

import com.weather.scalacass.syntax._    
case class TestTable(id: String, data1: Int, data2: Long)
val resultSet = session.execute(s"select * from test.testTable limit 10")
resultSet.one.as[TestTable]

Now I am attempting to make this more generic and I am unable to find the proper type constraint for the generic class.

import com.weather.scalacass.syntax._    
case class TestTable(id: String, data1: Int, data2: Long)

abstract class GenericReader[T] {
  val table: String
  val keyspace: String

  def getRows(session: Session): T = {
    val resultSet = session.execute(s"select * from $keyspace.$table limit 10")
    resultSet.one.as[T]
  }
}

I implement this class with the desired case class and attempt to call getRows on the created Object.

object TestTable extends GenericReader[TestTable] {
  val keyspace = "test"
  val table = "TestTable"
}

TestTable.getRows(session)

This throws an exception could not find implicit value for parameter ccd: com.weather.scalacass.CCCassFormatDecoder[T].

I am trying to add a type constraint to GenericReader in order to ensure the implicit conversion will work. However, I am unable to find the proper type. I am attempting to read through scala-cass in order to find the proper constraint but I have had no luck so far.

I would also be happy to use any other library that can achieve this.

Upvotes: 0

Views: 319

Answers (2)

Sander Hartlage
Sander Hartlage

Reputation: 36

Looks like as[T] requires an implicit value that you don't have in scope, so you'll need to require that implicit parameter in the getRows method as well.

def getRows(session: Session)(implicit cfd: CCCassFormatDecoder[T]): T

You could express this as a type constraint (what you were looking for in the original question) using context bounds:

abstract class GenericReader[T:CCCassFormatDecoder]

Upvotes: 2

Joe K
Joe K

Reputation: 18434

Rather than try to bound your generic T type, it might be easier to just pass through the missing implicit parameter:

abstract class GenericReader[T](implicit ccd: CCCassFormatDecoder[T]) {
  val table: String
  val keyspace: String

  def getRows(session: Session): T = {
    val resultSet = session.execute(s"select * from $keyspace.$table limit 10")
    resultSet.one.as[T]
  }
}

Finding a concrete value for that implicit can then be deferred to when you narrow that T to a specific class (like object TestTable extends GenericReader[TestTable])

Upvotes: 0

Related Questions