From 4519cb5088c396ad5756f43424e33a1c84642dda Mon Sep 17 00:00:00 2001 From: adamw Date: Wed, 19 Oct 2016 09:54:03 +0200 Subject: [PATCH] Conditional modifications --- README.md | 9 ++++++++- project/Build.scala | 2 +- .../com/softwaremill/quicklens/package.scala | 19 +++++++++++++++++++ .../quicklens/ModifySimpleTest.scala | 8 ++++++++ .../quicklens/SetToSimpleTest.scala | 16 ++++++++++++++++ 5 files changed, 52 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e4d79b0..954da3a 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,13 @@ person .modify(_.age).using(_ - 1) ```` +**Modify conditionally:** + +````scala +person.modify(_.address.street.name).setToIfDefined(Some("3 00 Ln.")) +person.modify(_.address.street.name).setToIf(shouldChangeAddress)("3 00 Ln.") +```` + **Modify several fields in one go:** ````scala @@ -183,7 +190,7 @@ Read [the blog](http://www.warski.org/blog/2015/02/quicklens-modify-deeply-neste Available in Maven Central: ````scala -val quicklens = "com.softwaremill.quicklens" %% "quicklens" % "1.4.7" +val quicklens = "com.softwaremill.quicklens" %% "quicklens" % "1.4.8" ```` Also available for [Scala.js](http://www.scala-js.org)! diff --git a/project/Build.scala b/project/Build.scala index 7cabbd8..dbd5803 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -6,7 +6,7 @@ import sbt._ object BuildSettings { val buildSettings = Defaults.coreDefaultSettings ++ Seq ( organization := "com.softwaremill.quicklens", - version := "1.4.7", + version := "1.4.8", scalaVersion := "2.11.8", crossScalaVersions := Seq("2.11.8", "2.12.0-RC1"), // Sonatype OSS deployment diff --git a/quicklens/src/main/scala/com/softwaremill/quicklens/package.scala b/quicklens/src/main/scala/com/softwaremill/quicklens/package.scala index a6546e8..d121917 100644 --- a/quicklens/src/main/scala/com/softwaremill/quicklens/package.scala +++ b/quicklens/src/main/scala/com/softwaremill/quicklens/package.scala @@ -56,11 +56,30 @@ package object quicklens { * @return A copy of the root object with the (deeply nested) field(s) modified. */ def using(mod: U => U): T = doModify(obj, mod) + /** + * Transform the value of the field(s) using the given function, if the condition is true. Otherwise, returns the + * original object unchanged. + * @return A copy of the root object with the (deeply nested) field(s) modified, if `condition` is true. + */ + def usingIf(condition: Boolean)(mod: U => U): T = if (condition) doModify(obj, mod) else obj /** * Set the value of the field(s) to a new value. * @return A copy of the root object with the (deeply nested) field(s) set to the new value. */ def setTo(v: U): T = doModify(obj, _ => v) + /** + * Set the value of the field(s) to a new value, if it is defined. Otherwise, returns the original object + * unchanged. + * @return A copy of the root object with the (deeply nested) field(s) set to the new value, if it is defined. + */ + def setToIfDefined(v: Option[U]): T = v.fold(obj)(setTo) + /** + * Set the value of the field(s) to a new value, if the condition is true. Otherwise, returns the original object + * unchanged. + * @return A copy of the root object with the (deeply nested) field(s) set to the new value, if `condition` is + * true. + */ + def setToIf(condition: Boolean)(v: => U): T = if (condition) setTo(v) else obj } implicit class AbstractPathModifyPimp[T, U](f1: T => PathModify[T, U]) { diff --git a/tests/src/test/scala/com/softwaremill/quicklens/ModifySimpleTest.scala b/tests/src/test/scala/com/softwaremill/quicklens/ModifySimpleTest.scala index 1fe968c..d150973 100644 --- a/tests/src/test/scala/com/softwaremill/quicklens/ModifySimpleTest.scala +++ b/tests/src/test/scala/com/softwaremill/quicklens/ModifySimpleTest.scala @@ -15,4 +15,12 @@ class ModifySimpleTest extends FlatSpec with Matchers { it should "modify several fields" in { modifyAll(b1)(_.b2, _.b3.each).using(duplicate) should be (b1dupdup) } + + it should "modify a case class field if the condition is true" in { + modify(a5)(_.name).usingIf(true)(duplicate) should be (a5dup) + } + + it should "leave a case class unchanged if the condition is flase" in { + modify(a5)(_.name).usingIf(false)(duplicate) should be (a5) + } } diff --git a/tests/src/test/scala/com/softwaremill/quicklens/SetToSimpleTest.scala b/tests/src/test/scala/com/softwaremill/quicklens/SetToSimpleTest.scala index 0aa84ec..19565b6 100644 --- a/tests/src/test/scala/com/softwaremill/quicklens/SetToSimpleTest.scala +++ b/tests/src/test/scala/com/softwaremill/quicklens/SetToSimpleTest.scala @@ -7,4 +7,20 @@ class SetToSimpleTest extends FlatSpec with Matchers { it should "set a new value of a single-nested case class field" in { modify(a1)(_.a2.a3.a4.a5.name).setTo("mod") should be (a1mod) } + + it should "set a new value in a case class if the condition is true" in { + modify(a1)(_.a2.a3.a4.a5.name).setToIf(true)("mod") should be (a1mod) + } + + it should "leave a case class unchanged if the condition is false" in { + modify(a1)(_.a2.a3.a4.a5.name).setToIf(false)("mod") should be (a1) + } + + it should "set a new value in a case class if it is defined" in { + modify(a1)(_.a2.a3.a4.a5.name).setToIfDefined(Some("mod")) should be (a1mod) + } + + it should "leave a case class unchanged if the value is not defined" in { + modify(a1)(_.a2.a3.a4.a5.name).setToIfDefined(None) should be (a1) + } }