@MariaLiviaCh
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec eleifend condimentum metus, at pretium orci sagittis et. Cras euismod justo ut tellus venenatis, et fermentum lectus feugiat. Nam pellentesque massa ac nulla semper ultricies. In eleifend tempor cursus.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec eleifend condimentum metus, at pretium orci sagittis et.
Cras euismod justo ut tellus venenatis, et fermentum lectus feugiat. Nam pellentesque massa ac nulla semper ultricies. In eleifend tempor cursus.
PATCH /api/:atomType/:id/:path
val atomData = MediaAtom(
url = "gu.com",
metadata = Some(Metadata(
commentsEnabled = Some(true),
channelId = Some("happy-friday"))))
val atomData = MediaAtom(
title = "Tech time video",
metadata = Some(Metadata(
commentsEnabled = Some(true),
channelId = Some("Scala"))))
/api/media/some-id/metadata.channelId
body: "Scala"
case class Employee(name: String, age: Int, manager: Boolean)
case class IceCream(name: String, numCherries: Int, inCone: Boolean)
String :: Int :: Boolean :: HNil
HList
Generic[IceCream].to(iceCream)
struct ExplainerAtom {
1: required string title
2: required string body
3: optional list<string> tags
}
libraryDependencies ++= Seq("com.twitter" %% "scrooge-core" % scroogeVersion)
Some sort of case classes?
You wish.
case class Atom(id: String, atomType: String, title: String, data: AtomData)
sealed trait AtomData
object AtomData {
case class Media(media: MediaAtom) extends AtomData
case class Explainer(explainer: ExplainerAtom) extends AtomData
}
case class MediaAtom(url: String, metadata: Option[Metadata])
case class ExplainerAtom(headline: String, body: String)
case class Metadata(commentsEnabled: Option[Boolean], channelId: Option[String])
val atomData = MediaAtom(url = "gu.com",
metadata = Some(Metadata(
commentsEnabled = Some(true),
channelId = Some("happy-friday"))))
val mediaAtom = Atom("some-id", "media", "Scala fun", AtomData.Media(atomData))
val genericRepr = LabelledGeneric[Atom].to(mediaAtom)
// "some-id" :: "media" :: "Scala fun" :: Media(MediaAtom(...)) :: HNil
val updatedGeneric = genericRepr + (Symbol("title") ->> "Updated title"))
// "some-id" :: "media" :: "Updated title" :: Media(MediaAtom(...)) :: HNil
val updatedGeneric2 = genericRepr + (Symbol(nestedField) ->> "Updated field"))
// error: Expression scala.Symbol.apply(ScalaFiddle.this.nestedField) does
// not evaluate to a constant or a stable reference value
Atom
id: String
type: String
title: String
data: AtomData
media: MediaAtom
metadata: Metadata
url: String
comments: Boolean
channelId: String
Convert to nested maps
Update the field in the map
trait Greetings[A] {
def message(creature: A): String
}
object Greetings {
implicit def humanMessage: Greetings[Human] = new Greetings[Human] {
override def message(human: Human): String = s"${human.name} says hello."
}
implicit def catMessage: Greetings[Cat] = new Greetings[Cat] {
override def message(cat: Cat): String = s"${cat.name} says meow."
}
implicit class GreetingsOps[A](creature: A) {
def greet(implicit greetings: Greetings[A]) = {
greetings.message(creature)
}
}
}
Human("Maria").greet // "Maria says hello."
Cat("Mistoffelees").greet // "Mistoffelees says meow."
Dog("Pollicle").greet // error: could not find implicit value for parameter message
trait ToMapRec[L <: HList] {
def apply(l: L): Map[String, Any]
}
object ToMapRec {
implicit def hconsToMapRecOption[K <: Symbol, V, R <: HList, T <: HList]
(implicit
wit: Witness.Aux[K],
gen: LabelledGeneric.Aux[V, R],
tmrT: Lazy[ToMapRec[T]],
tmrH: Lazy[ToMapRec[R]]
): ToMapRec[FieldType[K, Option[V]] :: T] = ???
}
trait ToMapRec[L <: HList] {
def apply(l: L): Map[String, Any]
}
...
implicit def hconsToMapRecOption[K <: Symbol, V, R <: HList, T <: HList]
(implicit
wit: Witness.Aux[K],
gen: LabelledGeneric.Aux[V, R],
tmrT: Lazy[ToMapRec[T]],
tmrH: Lazy[ToMapRec[R]]
): ToMapRec[FieldType[K, Option[V]] :: T] = new ToMapRec[FieldType[K, Option[V]] :: T] {
override def apply(l: FieldType[K, Option[V]] :: T): Map[String, Any] = {
tmrT.value(l.tail) + (wit.value.name -> l.head.map(elem => tmrH.value(gen.to(elem))))
}
}
...
val atomMap = atomData.toMap
val atomDataMap = Map(
"metadata" -> Some(Map(
"commentsEnabled" -> Some(false),
"channelId" -> Some("happy-friday"))),
"url" -> "gu.com")
trait FromMap[L <: HList] {
def apply(m: Map[String, Any]): Option[L]
}
...
implicit def hconsFromMapOption[K <: Symbol, V, R <: HList, T <: HList]
(implicit
witness: Witness.Aux[K],
gen: LabelledGeneric.Aux[V, R],
fromMapH: Lazy[FromMap[R]],
fromMapT: Lazy[FromMap[T]]
): FromMap[FieldType[K, Option[V]] :: T] = new FromMap[FieldType[K, Option[V]] :: T] {
def apply(m: Map[String, Any]): Option[FieldType[K, Option[V]] :: T] = {
m(witness.value.name) match {
case Some(v) =>
for {
r <- Typeable[Option[Map[String, Any]]].cast(Some(v))
h <- r.map(fromMapH.value(_))
t <- fromMapT.value(m)
} yield field[K](h.map(gen.from)) :: t
case None =>
for {
t <- fromMapT.value(m)
} yield field[K](None) :: t
}
}
}
...
val atomObj = to[Atom.Immutable].from(updatedAtom)