The Pair
class in Ratpack is an easy way to create a growing data structure, passed on via Promise
methods. A Pair
object has a left and right part containing data. These parts can even be other Pair
objects. Since Ratpack 1.4.0 the Promise
class has methods to set the right or left part of a Pair
: left
, flatLeft
, right
and flatRight
. The result of these methods is a Promise<Pair>
object. The input can be Promise
type or a Function
that can use a previous Promise
.
In the following example specification we use the different new methods to create a Pair
. We also create a simple Ratpack server with a asynchronous HTTP client implementation to simulate remote calls returning a Promise
:
package mrhaki import ratpack.exec.Promise import ratpack.func.Pair import ratpack.groovy.test.embed.GroovyEmbeddedApp import ratpack.http.HttpUrlBuilder import ratpack.http.client.HttpClient import ratpack.test.embed.EmbeddedApp import ratpack.test.exec.ExecHarness import spock.lang.AutoCleanup import spock.lang.Shared import spock.lang.Specification class PromisePairSpec extends Specification { /** * Simple server to serve /{value} and /{value}/size * GET requests. */ @Shared @AutoCleanup private EmbeddedApp serverApi = GroovyEmbeddedApp.of({ handlers { get(':value') { render pathTokens.value } get(':value/size') { render String.valueOf(pathTokens.value.size()) } } }) /** * Asynchronous HTTP client. */ @AutoCleanup private HttpClient api = HttpClient.of { client -> client.poolSize 1 } def "set right side of Pair with result of function using initial Promise value"() { expect: ExecHarness.yieldSingle { Promise.value('Ratpack') // Use Promise 'Ratpack' in right method as argument. .right { s -> s.size() } }.value == Pair.of('Ratpack', 7) } def "set right side of Pair with result of other Promise"() { expect: ExecHarness.yieldSingle { Promise.value('Ratpack is') // Use Promise value .right(getApiText('cool')) }.value == Pair.of('Ratpack is', 'cool') } def "set right side of Pair with result Promise of function using initial Promise value"() { expect: ExecHarness.yieldSingle { Promise.value('Ratpack') // Use Promise 'Ratpack' in flatRight method as argument. .flatRight { s -> getApiText("${s}/size") } }.value == Pair.of('Ratpack', '7') } def "set right side of Pair with result Promise of function using initial Promise value using flatMap"() { expect: ExecHarness.yieldSingle { Promise.value('Ratpack') // Use Promise 'Ratpack' in flatMap method as argument. // This is the way to set the Pair values // before the flatRight method was added .flatMap { s -> getApiText("${s}/size").map { content -> Pair.of(s, content) } } }.value == Pair.of('Ratpack', '7') } def "set left side of Pair with result of function using initial Promise value"() { expect: ExecHarness.yieldSingle { Promise.value('Ratpack') // Use Promise 'Ratpack' in left method as argument. .left { s -> s.size() } }.value == Pair.of(7, 'Ratpack') } def "set left side of Pair with result of other Promise"() { expect: ExecHarness.yieldSingle { Promise.value('cool') // Get Promise value without using Promise 'cool' value. .left(getApiText('Ratpack is')) }.value == Pair.of('Ratpack is', 'cool') } def "set left side of Pair with result Promise of function using initial Promise value"() { expect: ExecHarness.yieldSingle { Promise.value('Ratpack') // Use Promise 'Ratpack' in flatLeft method as argument. .flatLeft { s -> getApiText("${s}/size") } }.value == Pair.of('7', 'Ratpack') } private Promise<String> getApiText(final String path) { api.get(createRequest(path)) .map { response -> response.body.text } } private URI createRequest(final String path) { HttpUrlBuilder.base(serverApi.address).path(path).build() } }
Written with Ratpack 1.4.3.