Question: Creating generic update function for Slick 3.1.1

Question

Creating generic update function for Slick 3.1.1

Answers 1
Added at 2016-12-28 08:12
Tags
Question

I have this fucntion:

 def updateInvoiceAdminStatusField(id: Int, newAdminStatus: AdminStatus): Future[Int] = {


    db.run {

      val adminStatus: Query[Rep[AdminStatus], AdminStatus, Seq] = InvoicesTable.filter(invoice => invoice.id === id).map(invoice => invoice.status)

      adminStatus.update(newAdminStatus)
    }
  }

I thought of making it generic:

   def updateInvoiceField[T](id: Int, fieldExtractor: (Invoices) => Rep[T], newValue: T): Future[Int] = {

    db.run {

      val adminStatus = InvoicesTable.filter(invoice => invoice.id === id).map(invoice => {

        fieldExtractor(invoice)
      })

      adminStatus.update(newValue)
    }
  }

But this does not compile. Can somebody assist?

Answers
nr: #1 dodano: 2016-12-28 11:12

It's nearly good. With small changes like below it should work:

// I added below T: ColumnType
def updateInvoiceField[T: ColumnType](id: Int, fieldExtractor: (Invoices) => Rep[T], newValue: T): Future[Int] = {

  db.run {
      val adminStatus = InvoicesTable.filter(invoice => invoice.id === id).map(invoice => {
          fieldExtractor(invoice)
      })

      adminStatus.update(newValue)
  }
}

Notice I added this : ColumnType which basically mean you need to have proper implicit in scope - specifically the one that would convert T => ColumnType[T]. That's simply because otherwise T could be anything and Slick wouldn't be able to figure out how to convert it.

So for things like String, Int etc. you obviously have proper conversations already in place (imported from api in profile/driver). For you custom types you would need to use MappedColumnType to have proper conversion supplied. Example below (typesafe ID):

implicit def columnType[T]: BaseColumnType[Id[T]] =
    MappedColumnType.base[Id[T], Long](toLong, fromLong)

private def fromLong[T](dbId: Long): Id[T] = Id(dbId)

private def toLong[T](id: Id[T]): Long = id.value
Source Show
◀ Wstecz