Ratpacked: Creating Pairs From Promises
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 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.