1
votes

So, the problem is in the title, but here are the details.

I have two case classes:

case class JourneyGroup(id: Option[Int] = None,
                        key: UUID,
                        name: String,
                        data: Option[JsValue],
                        accountId: Int,
                        createdAt: DateTime = DateTime.now,
                        createdById: Int,
                        updatedAt: Option[DateTime] = None,
                        updatedById: Option[Int] = None,
                        deletedAt: Option[DateTime] = None,
                        deletedById: Option[Int] = None)

and

case class JourneyGroupApi(id: Option[Int] = None,
                           key: UUID,
                           name: String,
                           data: Option[JsValue],
                           accountId: Int,
                           createdAt: DateTime = DateTime.now,
                           createdById: Int,
                           updatedAt: Option[DateTime] = None,
                           updatedById: Option[Int] = None,
                           deletedAt: Option[DateTime] = None,
                           deletedById: Option[Int] = None,
                           parties: Seq[Party] = Seq.empty[Party])

Background: the reason for having these two separate classes is the fact that slick does not support collections, and I do need collections of related objects that I build manually. Bottom line, I could not make it work with a single class.

What I need is an easy way to convert from one to another. At this point, to unblock myself, I created a manual conversion:

def toJourneyGroupApi(parties: Seq[Party]): JourneyGroupApi = JourneyGroupApi(
    id = id,
    key = key,
    name = name,
    data = data,
    accountId = accountId,
    createdAt = createdAt,
    createdById = createdById,
    updatedAt = updatedAt,
    updatedById = updatedById,
    deletedAt = deletedAt,
    deletedById = deletedById,
    parties = parties
  )

Which is working, but extremely ugly and requires a lot of maintenance.

One thing that I tried doing is:

  1. convert the source object to tuple

  2. Add an element to that tuple using shapeless

  3. and build a target object from resulting tuple

    import shapeless._ import syntax.std.tuple._

    val groupApi = (JourneyGroup.unapply(group).get :+ Seq.empty[Party])(JourneyGroupApi.tupled)

But, this thing is claiming, that the result of :+ is not tuple, even though in console:

Party.unapply(p).get :+ Seq.empty[Participant]

res0: (Option[Int], model.Parties.Type.Value, Int, Int, org.joda.time.DateTime, Int, Option[org.joda.time.DateTime], Option[Int], Option[org.joda.time.DateTime], Option[Int], Seq[model.Participant]) = (None,client,123,234,2016-11-12T03:55:24.006-08:00,987,None,None,None,None,List())

What am I doing wrong? Maybe there is another way of achieving this.

1

1 Answers

1
votes

Could you consider Composition?

case class JourneyGroup(
  ...
)
case class JourneyGroupApi(
  journeyGroup: JourneyGroup=JourneyGroup(),
  parties: Seq[Party] = Seq()
)

Converting a journeyGroup would just be something like JourneyGroupApi(journeyGroup,parties) and "converting" a journeyGroupApi would be a matter of accessing journeyGroupApi.journeyGroup. You could perhaps come up with names that worked better for this case. Not sure if this approach would fit the rest of your code. In particular referencing journeyGroup attributes in a journeyGroupApi will be one extra level, e.g. journeyGroupApi.journeyGroup.accountId. (This could potentially be mitigated by "shortcut" definitions on journeyGroupApi like lazy val accountId = journeyGroup.accountId.)

Inheritance might also be an approach to consider with a base case class of JourneyGroup then a normal class (not case class) that extends it with parties as the extra attribute. This option is discussed further in this SO thread.