diff --git a/docs/docs/supported-transformations.md b/docs/docs/supported-transformations.md index 5cb344fa0..2fc6cf656 100644 --- a/docs/docs/supported-transformations.md +++ b/docs/docs/supported-transformations.md @@ -2917,6 +2917,37 @@ Or we might want to redirect two subtypes into the same target subtype. For that // Bar(a = 10) ``` +!!! notice + + If one needs to handle this case in but nested inside a `case class`/`Option`/`Either`/collection, one can use + `.withFieldRenamed` with proper selectors: + + ```scala + //> using dep io.scalaland::chimney::{{ chimney_version() }} + //> using dep com.lihaoyi::pprint::{{ libraries.pprint }} + import io.scalaland.chimney.dsl._ + + sealed trait Source + object Source { + case object Foo extends Source + case class Baz(a: Int) extends Source + } + + sealed trait Target + object Target { + case object Foo extends Target + case class Bar(a: Int) extends Target + } + + pprint.pprintln( + List(Source.Baz(10): Source).into[List[Target]] + .withFieldRenamed(_.everyItem.matching[Source.Baz], _.everyItem.matching[Target.Bar]) + .transform + ) + // expected output: + // List(Bar(a = 10)) + ``` + !!! notice While `sealed` hierarchies, Scala 3 `enum`s and Java `enum`s fall into the same category of Algebraic Data Types, @@ -3081,6 +3112,55 @@ If the computation needs to allow failure, there is `.withSealedSubtypeHandledPa // Right(value = Buzz) ``` +!!! notice + + If one needs to handle this case in but nested inside a `case class`/`Option`/`Either`/collection, one can use + `.withFieldComputedFrom`/`.withFieldComputedPartialFrom` with proper selectors: + + ```scala + //> using dep io.scalaland::chimney::{{ chimney_version() }} + //> using dep com.lihaoyi::pprint::{{ libraries.pprint }} + import io.scalaland.chimney.dsl._ + import io.scalaland.chimney.partial + + sealed trait Foo + object Foo { + case class Baz(a: String) extends Foo + case object Buzz extends Foo + } + sealed trait Bar + object Bar { + case class Baz(a: String) extends Bar + case object Fizz extends Bar + case object Buzz extends Bar + } + + pprint.pprintln( + List(Bar.Baz("value"): Bar, Bar.Fizz: Bar, Bar.Buzz: Bar) + .into[List[Foo]] + .withFieldComputedFrom(_.everyItem.matching[Bar.Fizz.type])(_.everyItem, fizz => Foo.Baz(fizz.toString)) + .transform + ) + // expected output: + // List(Baz(a = "value"), Baz(a = "Fizz"), Buzz) + + pprint.pprintln( + List(Bar.Baz("value"): Bar, Bar.Fizz: Bar, Bar.Buzz: Bar) + .intoPartial[List[Foo]] + .withFieldComputedPartialFrom(_.everyItem.matching[Bar.Fizz.type])(_.everyItem, fizz => partial.Result.fromEmpty) + .transform + .asEither + ) + // expected output: + // Left( + // value = Errors( + // errors = NonEmptyErrorsChain( + // Error(message = EmptyValue, path = Path(elements = List(Index(index = 1)))) + // ) + // ) + // ) + ``` + !!! notice While `sealed` hierarchies, Scala 3 `enum`s and Java `enum`s fall into the same category of Algebraic Data Types, @@ -3325,6 +3405,9 @@ If the computation needs to allow failure, there is `.withSealedSubtypeHandledPa } ``` +If one needs to handle this case in but nested inside a `case class`/`Option`/`Either`/collection, one can use +`.withFieldRenamed` with a proper selectors: + ### Customizing subtype name matching Be default names are matched with a `String` equality - `Subtype` would be considered a match for another `Subtype` diff --git a/docs/docs/troubleshooting.md b/docs/docs/troubleshooting.md index a65c6b70b..af275baa4 100644 --- a/docs/docs/troubleshooting.md +++ b/docs/docs/troubleshooting.md @@ -1145,8 +1145,8 @@ Here are some features it shares with Chimney (Ducktape's code based on GitHub P // ) ``` - Chimney doesn't allow handling sealed subtypes/enum cases when nested, and require using implicit `Transformer` - which would handle them as top level: + Chimney allows handling nested sealed subtypes/enum cases when by using + `.withFieldComputedFrom`/'.withFieldComputedPartial`/`.withFieldRenamed` using proper selectors: ```scala // file: snippet.scala - part of Ductape counterpart 2 @@ -1191,23 +1191,17 @@ Here are some features it shares with Chimney (Ducktape's code based on GitHub P ) import io.scalaland.chimney.dsl.* - import io.scalaland.chimney.Transformer - pprint.pprintln { - // There is no direct analogue to nested: - // Case.const(_.paymentMethods.element.at[wire.PaymentMethod.Transfer], domain.PaymentMethod.Cash) - // so this has to be handled "top level" by creating implicit/given. - given Transformer[wire.PaymentMethod, domain.PaymentMethod] = Transformer - .define[wire.PaymentMethod, domain.PaymentMethod] - .withEnumCaseHandled[wire.PaymentMethod.Transfer](_ => domain.PaymentMethod.Cash) - .buildTransformer - + pprint.pprintln( wirePerson .into[domain.Person] .withFieldConst(_.firstName, "Jane") - // implicit instead of nested handling for withEnumCaseHandled + .withFieldComputedFrom(_.paymentMethods.everyItem.matching[wire.PaymentMethod.Transfer])( + _.paymentMethods.everyItem, + _ => domain.PaymentMethod.Cash + ) .transform - } + ) // expected output: // Person( // firstName = "Jane",