Scala Reflection to update a case class val

reflection, scala

Solution

This question was answered here to help other with this kind of problem. I end up using this code to execute the copy method of my case classes using scala reflection.

import reflect._
import scala.reflect.runtime.universe._
import scala.reflect.runtime._

class Empty

val mirror = universe.runtimeMirror(getClass.getClassLoader)
// paramName is the parameter that I want to replacte the value
// paramValue is the new parameter value
def updateParam[R : ClassTag](r: R, paramName: String, paramValue: Any): R = {

  val instanceMirror = mirror.reflect(r)
  val decl = instanceMirror.symbol.asType.toType
  val members = decl.members.map(method => transformMethod(method, paramName, paramValue, instanceMirror)).filter {
    case _: Empty => false
    case _ => true
  }.toArray.reverse

  val copyMethod = decl.declaration(newTermName("copy")).asMethod
  val copyMethodInstance = instanceMirror.reflectMethod(copyMethod)

  copyMethodInstance(members: _*).asInstanceOf[R]
}

def transformMethod(method: Symbol, paramName: String, paramValue: Any, instanceMirror: InstanceMirror) = {
  val term = method.asTerm
  if (term.isAccessor) {
    if (term.name.toString == paramName) {
      paramValue
    } else instanceMirror.reflectField(term).get
  } else new Empty
}

With this I can execute the copy method of my case classes, replacing a determined field value.

Problem

I'm using scala and slick here, and I have a baserepository which is responsible for doing the basic crud of my classes. For a design decision, we do have updatedTime and createdTime columns all handled by the application, and not by triggers in database. Both of this fields are joda DataTime instances. Those fields are defined in two traits called HasUpdatedAt, and HasCreatedAt, for the tables ``` trait HasCreatedAt { val createdAt: Option[DateTime] } case class User(name:String,createdAt:Option[DateTime] = None) extends HasCreatedAt ``` I would like to know how can I use reflection to call the user copy method, to update the createdAt value during the database insertion method. Edit after @vptron and @kevin-wright comments I have a repo like this ``` trait BaseRepo[ID, R] { def insert(r: R)(implicit session: Session): ID } ``` I want to implement the insert just once, and there I want to createdAt to be updated, that's why I'm not using the copy method, otherwise I need to implement it everywhere I use the createdAt column.

Original source

Related problems