trait FutureSugar extends AnyRef
Trait providing an implicit class that adds a validating
method to
Future
, which takes one or more validation functions and returns either the
same Future
if either the Future
had already failed or its value
passes all the functions, or ValidationFailedException
containing an error message
describing the first validation that failed.
Here's an example validation method, which passes if the given Int
is evenly
divisible by 10 (i.e., the result will be Pass
). If the value does not pass
this test, the result is a Fail
containing a helpful error message string.
scala> import org.scalactic._ import org.scalactic._ scala> import FutureSugar._ import org.scalactic.FutureSugar._ scala> import scala.concurrent.Future import scala.concurrent.Future scala> import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.ExecutionContext.Implicits.global scala> def isRound(i: Int): Validation[ErrorMessage] = | if (i % 10 == 0) Pass else Fail(i + " was not a round number") isRound: (i: Int)org.scalactic.Validation[org.scalactic.ErrorMessage]
Validation will be attempted on a successful Try
. If the validation succeeds, the
resulting Future
will be the same successful Future
with the same value. (A
"validation" only transforms the Future
if the validation fails, otherwise it is the
same Future
. The only difference is its value has now been proven valid.)
In the following example, a successful Future[Int]
with the value 100
passes the validation (which checks whether 100 is evenly divisible by 10), therefore
the result of the validating
call is the same successful Future
with the same value.
scala> val fut100 = Future(100) fut100: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@67f9c9c6 scala> fut100.value res0: Option[scala.util.Try[Int]] = Some(Success(100)) scala> val round100 = fut100.validating(isRound) round100: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@1ac2f0d1 scala> round100.value res1: Option[scala.util.Try[Int]] = Some(Success(100))
If validation fails, the successful Future
will be transformed into a failed one, with
a ValidationFailedException
that contains the error message
returned by the validation function. In the following example, 42 fails the validation because it
is not evenly divisible by 10:
scala> val fut42 = Future(42) fut42: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@19c6e4d1 scala> fut42.value res2: Option[scala.util.Try[Int]] = Some(Success(42)) scala> val round42 = fut42.validating(isRound) round42: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@b5175d scala> round42.value res3: Option[scala.util.Try[Int]] = Some(Failure(org.scalactic.exceptions.ValidationFailedException: 42 was not a round number))
If validating
is called on a failed Future
, it just returns the same failed Future
:
scala> val futEx = Future[Int] { throw new Exception("oops!") } futEx: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@3ba0299c scala> futEx.value res4: Option[scala.util.Try[Int]] = Some(Failure(java.lang.Exception: oops!)) scala> val roundEx = futEx.validating(isRound) roundEx: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@22bf1acf scala> roundEx.value res5: Option[scala.util.Try[Int]] = Some(Failure(java.lang.Exception: oops!))
The validating
method accepts one or more validation functions. If you
pass more than one, they will be tried in order up until the first failure, whose
error message will appear in the ValidationFailedException
. In other words,
validating
will short circuit at the first error and return that. It
will not accumulate errors. For example, the following validation will short circuit
after the isDivBy3
function fails:
scala> def isDivBy3(i: Int): Validation[ErrorMessage] = | if (i % 3 == 0) Pass else Fail(i + " was not divisible by 3") isDivBy3: (i: Int)org.scalactic.Validation[org.scalactic.ErrorMessage] scala> def isAnswerToLifeTheUniverseAndEverything(i: Int): Validation[ErrorMessage] = | if (i == 42) Pass else Fail(i + " did not equal 42") isAnswerToLifeTheUniverseAndEverything: (i: Int)org.scalactic.Validation[org.scalactic.ErrorMessage] scala> val futShort = fut100.validating(isRound, isDivBy3, isAnswerToLifeTheUniverseAndEverything) futShort: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@30bb943e scala> futShort.value res11: Option[scala.util.Try[Int]] = Some(Failure(org.scalactic.exceptions.ValidationFailedException: 100 was not divisible by 3))
- Source
- FutureSugar.scala
- Alphabetic
- By Inheritance
- FutureSugar
- AnyRef
- Any
- Hide All
- Show All
- Public
- All
Type Members
-
implicit
class
Futureizer[T] extends AnyRef
Implicit class that adds a
validation
method toFuture
, which takes one or more functions that validate theFuture
's value.Implicit class that adds a
validation
method toFuture
, which takes one or more functions that validate theFuture
's value.See the main documentation for trait
FutureSugar
for more detail and examples.