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.