Bohdan Petrenko
Bohdan Petrenko

Reputation: 1175

Convert one case class to another with the same structure but with one additional field

Let's say I have two case classes:

case class C1(a: Int, b: String)
case class C2(a: Int, b: String, c: Long = 0)

I want to convert instance of C1 to C2 and then set additional field c. I found out the following solution:

C1.unapply(C1(1, "s1")).map(v => C2(v._1, v._2, 7l))

But specifying parameters one by one is not applicable, because real case class will have at least 15 params. Any ideas how to solve it?

Upvotes: 6

Views: 912

Answers (2)

Felix
Felix

Reputation: 8505

I think what you need is closer to

https://github.com/scalalandio/chimney

case class MakeCoffee(id: Int, kind: String, addict: String)
case class CoffeeMade(id: Int, kind: String, forAddict: String, at: ZonedDateTime)

val command = MakeCoffee(id = Random.nextInt,
                         kind = "Espresso",
                         addict = "Piotr")

import io.scalaland.chimney.dsl._

val event = command.into[CoffeeMade]
  .withFieldComputed(_.at, _ => ZonedDateTime.now)
  .withFieldRenamed(_.addict, _.forAddict)
  .transform

Upvotes: 4

Rex
Rex

Reputation: 568

This solution can be done by doing something like this thread.

How to append or prepend an element to a tuple in Scala

implicit class TupOps2[A, B](val x: (A, B)) extends AnyVal {
  def :+[C](y: C) = (x._1, x._2, y)
  def +:[C](y: C) = (y, x._1, x._2)
}

Usage:

val c1      = new C1(1, "s1")
val longVal = 0L

scala> C1.unapply(c1).map(r => (r :+ longVal))
res0: Option[(Int, String, Long)] = Some((1,s1,0))

scala> C1.unapply(c1).map(r => (C2.apply _) tupled (r:+ longVal))
res45: Option[C2] = Some(C2(1,s1,0))

Hope it helps :)

Upvotes: 5

Related Questions