Search code examples
scalageneric-programmingshapeless

How to create generated objects in shapeless


Suppose I have a normalized database model for a generic type that comes in like this:

case class BaseModel(id: String, 
                     createdBy: String,
                     attr1: Option[String] = None,
                     attr2: Option[Int] = None, 
                     attr3: Option[LocalDate] = None)

Given a sequence of BaseModel, if all the fields of a certain Option attribute are not populated, can shapeless create a reduced model for me?

For example suppose that all the attr1 fields are empty. Without me having to specify the object before hand can shapeless create a generic object that looks like this?

case class BaseModel(id: String, 
                     createdBy: String,
                     attr2: Option[Int] = None, 
                     attr3: Option[LocalDate] = None)

Solution

  • What Shapeless can do is, given two case classes, create an object of one of them from an object of another.

    import java.time.LocalDate
    import shapeless.LabelledGeneric
    import shapeless.record._
    
    case class BaseModel(id: String,
                         createdBy: String,
                         attr1: Option[String] = None,
                         attr2: Option[Int] = None,
                         attr3: Option[LocalDate] = None)
    
    case class BaseModel1(id: String,
                          createdBy: String,
                          attr2: Option[Int] = None,
                          attr3: Option[LocalDate] = None)
    
    val bm = BaseModel(
      id = "cff4545gvgf", 
      createdBy = "John Doe", 
      attr2 = Some(42), 
      attr3 = Some(LocalDate.parse("2018-11-03"))
    )  // BaseModel(cff4545gvgf,John Doe,None,Some(42),Some(2018-11-03))
    val hlist = LabelledGeneric[BaseModel].to(bm)
    val hlist1 = hlist - 'attr1
    val bm1 = LabelledGeneric[BaseModel1].from(hlist1)    
       // BaseModel1(cff4545gvgf,John Doe,Some(42),Some(2018-11-03))
    

    But Shapeless can't create a new case class. If you need a new case class to be created automatically you can write a macro.