I am writing a function to persist some data to a Slick postgres database. Here is my table persisting ClientRow
objects:
class ClientTable(tag: Tag) extends Table[ClientRow](tag, "clients") {
def clientId = column[Long]("client_id", O.PrimaryKey, O.AutoInc)
...
override def * =
(clientId, phoneNumber, firstName, lastName, trainerId, dateRegistered) <> (ClientRow.tupled, ClientRow.unapply _)
}
I tried writing the following function to inject the table and database dependencies through composition:
type PersistClient[A <: AbstractTable[_]] =
DatabaseDef => TableQuery[A] => ClientInfo => Future[ClientId]
val persist: PersistClient[ClientTable] = db =>
clients =>
info => {
val action = clients.returning(
clients.map(_.clientId) += toRow(info)
)
db.run(action).map(constructId(_))
}
Here ClientInfo and ClientId are just case classes with data. toRow
has signature ClientInfo => ClientRow
, it converts the strongly typed/highly structured data in the Info object to more primitive data for SQL. constructId
creates a string ID out of the Long for logging readability (I like id.client.<number>
)
Under toRow
I get the following error:
type mismatch;
found : messager.Client.persistence.ClientRow
required: Long
Strangely, if I write the same function while injecting the dependencies into the class that houses this function as so:
val persistClient: ClientInfo => Future[ClientId] = info => {
val action = clients.returning(clients.map(_.clientId)) += toRow(info)
db.run(action).map(constructId(_))
}
Here clients
and db
are the same types as before, but are just injected into the class as dependencies rather than inputs to a function. What gives? Why can't my nice curried code compile?
It looks like the argument to clients.returning
is a insert that returns the number of rows changed. That doesn't look right, and is different from the version you have that works.