scala - Slick: Avoiding asInstanceOf[T] and Improving Type signature -
the code below works, can't think doing inappropriate asinstanceof[b]
cast.
essentially, after passing tablequery
of type, want mapper
turn action take results , map
list of daos according function pass it.
what stuck on type of function, or perhaps how expose inner type of tablequery type. want [b <: tableelementtype]
f: b => a
instead of potentially brutal cast b.
i guess think know going agencyrow
in example below map agencydao, how can capture in type signature of method?
mapper
def mapper[a <: basedao, b <: databaseaccessobject, t <: tablequery[e], e <: abstracttable[_]](query: t, f: b => a) : seq[a] = { val result = exec(query.result) result.map(o => f(o.asinstanceof[b])) } def exec[t](action: dbio[t]): t = await.result(db.run(action), 4 seconds)
consuming mapper (test code)
val list = mapper[agencydao, agencyrow, tablequery[agency], agency](agencies, agencydaodomainobject.convertfromrow) list.length should equal(75)
slick schema
case class agencyrow(id: int, name: option[string] = none) extends databaseaccessobject class agency(_tabletag: tag) extends table[agencyrow](_tabletag, "agency") { def * = (id, name) <>(agencyrow.tupled, agencyrow.unapply) def ? = (rep.some(id), name).shaped.<>({ r => import r._; _1.map(_ => agencyrow.tupled((_1.get, _2))) }, (_: any) => throw new exception("inserting ? projection not supported.")) val id: rep[int] = column[int]("id", o.autoinc, o.primarykey) val name: rep[option[string]] = column[option[string]]("name", o.length(200, varying = true), o.default(none)) } lazy val agency = new tablequery(tag => new agency(tag))enter code here
dao mapper
package object implicits { implicit class domainobjectops[a <: basedao](a: a)(implicit ev: domainobject[a]) { def name = ev.name(a) def id = ev.id(a) } } trait basedao trait domainobject[a <: basedao] { def id(a: a): int def name(a: a): string } case class agencydao(val id: int, val name: string) extends basedao object agencydao { implicit object agencydaodomainobject extends domainobject[agencydao] { def converttorow(o: agencydao) = agencyrow(o.id, some(o.name)) def convertfromrow(o: agencyrow) = agencydao(o.id, o.name.getorelse("")) override def id(a: agencydao) = a.id override def name(a: agencydao) = a.name } }
in case else might possibly find relevant or instructive: rather call result
on query inside mapper, passed in result
called, returns dbioaction[r]
. slick has convenient alias dbio[r]
, , r
can asked extend seq[b]
eliminating need cast. now:
updated mapper
def resultmapper[a <: basedao, b <: databaseaccessobject, s <: dbio[seq[b]]](action: s)(implicit rowmapper: b => a) : seq[a] = { val result = exec(action) result.map(rowmapper) }
updated call
implicit val rowmapper: agencyrow => agencydao = agencydaodomainobject.convertfromrow val action = agencies.result //turns query dbioaction val list = resultmapper[agencydao, agencyrow, dbio[seq[agencyrow]]](action)
Comments
Post a Comment