Skip to content

Commit

Permalink
Merge pull request scanamo#73 from guardian/sbt-microsite
Browse files Browse the repository at this point in the history
Add prettier docs using sbt-microsite
  • Loading branch information
Phil Wills authored Dec 8, 2016
2 parents 5efa08c + dff8c76 commit 7cce578
Show file tree
Hide file tree
Showing 14 changed files with 396 additions and 8 deletions.
9 changes: 8 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,12 @@ cache:
before_cache:
- find $HOME/.sbt -name "*.lock" -type f -delete -print
- find $HOME/.ivy2/cache -name "ivydata-*.properties" -type f -delete -print
script: "sbt clean coverage test"
before_install:
- export PATH=${PATH}:./vendor/bundle
install:
- rvm use 2.2.3 --install --fuzzy
- gem update --system
- gem install sass
- gem install jekyll -v 3.2.1
script: "sbt clean coverage test makeMicrosite"
after_success: "sbt coverageReport coveralls"
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ scala> import cats.syntax.either._

scala> val client = LocalDynamoDB.client()
scala> import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType._
scala> val farmersTableResult = LocalDynamoDB.createTable(client)("winners")('name -> S)
scala> val winnersTableResult = LocalDynamoDB.createTable(client)("winners")('name -> S)

scala> case class LuckyWinner(name: String, shape: String)
scala> def temptWithGum(child: LuckyWinner): LuckyWinner = child match {
Expand Down
31 changes: 26 additions & 5 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ libraryDependencies ++= Seq(
"com.amazonaws" % "aws-java-sdk-dynamodb" % "1.11.52",
"com.chuusai" %% "shapeless" % "2.3.2",
"org.typelevel" %% "cats-free" % "0.8.1",

"com.github.mpilquist" %% "simulacrum" % "0.10.0",

"org.typelevel" %% "macro-compat" % "1.1.1",
Expand Down Expand Up @@ -50,9 +49,12 @@ startDynamoDBLocal := startDynamoDBLocal.dependsOn(compile in Test).value
test in Test := (test in Test).dependsOn(startDynamoDBLocal).value
testOptions in Test += dynamoDBLocalTestCleanup.value

site.settings
site.includeScaladoc()
import com.typesafe.sbt.SbtSite.SiteKeys.makeSite
tut := tut.dependsOn(startDynamoDBLocal).value

tut <<= (tut, stopDynamoDBLocal){ (tut, stop) => tut.doFinally(stop)}

enablePlugins(MicrositesPlugin, SiteScaladocPlugin)

includeFilter in makeSite := "*.html" | "*.css" | "*.png" | "*.jpg" | "*.gif" | "*.js" | "*.yml"
ghpages.settings
com.typesafe.sbt.SbtGhPages.GhPagesKeys.ghpagesNoJekyll := false
Expand All @@ -65,7 +67,7 @@ doctestTestFramework := DoctestTestFramework.ScalaTest

parallelExecution in Test := false

homepage := Some(url("https://github.com/guardian/scanamo"))
homepage := Some(url("https://guardian.github.io/scanamo/"))
licenses := Seq("Apache V2" -> url("http://www.apache.org/licenses/LICENSE-2.0.html"))
publishMavenStyle := true
publishArtifact in Test := false
Expand Down Expand Up @@ -102,3 +104,22 @@ releaseProcess := Seq[ReleaseStep](
ReleaseStep(action = Command.process("sonatypeReleaseAll", _)),
pushChanges
)

micrositeName := "Scanamo"
micrositeDescription := "Scanamo: simpler DynamoDB access for Scala"
micrositeAuthor := "Scanamo Contributors"
micrositeGithubOwner := "guardian"
micrositeGithubRepo := "scanamo"
micrositeBaseUrl := "scanamo"
micrositeDocumentationUrl := "/scanamo/latest/api"
micrositeHighlightTheme := "color-brewer"
micrositePalette := Map(
"brand-primary" -> "#951c55",
"brand-secondary" -> "#005689",
"brand-tertiary" -> "#00456e",
"gray-dark" -> "#453E46",
"gray" -> "#837F84",
"gray-light" -> "#E3E2E3",
"gray-lighter" -> "#F4F3F4",
"white-color" -> "#FFFFFF"
)
3 changes: 2 additions & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ addSbtPlugin("com.github.tkawachi" % "sbt-doctest" % "0.4.0")

resolvers += "jgit-repo" at "http://download.eclipse.org/jgit/maven"
addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.5.4")
addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "0.8.2")
addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.1.0")
addSbtPlugin("com.fortysevendeg" % "sbt-microsites" % "0.3.3")

addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.0")
addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "0.5.0")
Expand Down
24 changes: 24 additions & 0 deletions src/main/resources/microsite/data/menu.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
options:
- title: Put and Get
url: put-get.html

- title: Scanning
url: scanning.html

- title: Querying
url: querying.html

- title: Updating
url: updating.html

- title: Using Indexes
url: using-indexes.html

- title: Asynchronous Requests
url: asynchronous.html

- title: Custom Formats
url: custom-formats.html

- title: Batch Operations
url: batch-operations.html
40 changes: 40 additions & 0 deletions src/main/tut/asynchronous.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
layout: docs
title: Asynchronous Requests
position: 8
---

### Non-blocking requests

Whilst for simplicity most examples in these documents are based on synchronous
requests to DynamoDB, Scanamo supports making the requests asynchronously with
a client that implements the `AmazonDynamoDBAsync` interface:

```tut:silent
import com.gu.scanamo._
import com.gu.scanamo.syntax._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
val client = LocalDynamoDB.client()
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType._
LocalDynamoDB.createTable(client)("farm")('name -> S)
case class Farm(animals: List[String])
case class Farmer(name: String, age: Long, farm: Farm)
val farmTable = Table[Farmer]("farm")
val ops = for {
_ <- farmTable.putAll(Set(
Farmer("Boggis", 43L, Farm(List("chicken"))),
Farmer("Bunce", 52L, Farm(List("goose"))),
Farmer("Bean", 55L, Farm(List("turkey")))
))
bunce <- farmTable.get('name -> "Bunce")
} yield bunce
```
```tut:book
//concurrent.Await.result(ScanamoAsync.exec(client)(ops), 5.seconds)
```

Note that `AmazonDynamoDBAsyncClient` uses a thread pool internally.
39 changes: 39 additions & 0 deletions src/main/tut/batch-operations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
layout: docs
title: Batch Operations
position: 9
---

### Batch Operations

Many operations against Dynamo can be performed in batches. Scanamo
has support for putting, getting and deleting in batches

```tut:silent
import com.gu.scanamo._
import com.gu.scanamo.syntax._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
val client = LocalDynamoDB.client()
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType._
LocalDynamoDB.createTable(client)("lemmings")('role -> S)
case class Lemming(role: String, number: Long)
```

```tut:book
val lemmingsTable = Table[Lemming]("lemmings")
val ops = for {
_ <- lemmingsTable.putAll(Set(
Lemming("Walker", 99), Lemming("Blocker", 42), Lemming("Builder", 180)
))
bLemmings <- lemmingsTable.getAll('role -> Set("Blocker", "Builder"))
_ <- lemmingsTable.deleteAll('role -> Set("Walker", "Blocker"))
survivors <- lemmingsTable.scan()
} yield (bLemmings, survivors)
val (bLemmings, survivors) = Scanamo.exec(client)(ops)
bLemmings.flatMap(_.toOption)
survivors.flatMap(_.toOption)
```
40 changes: 40 additions & 0 deletions src/main/tut/custom-formats.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
layout: docs
title: Custom Formats
position: 6
---

### Custom Formats

Scanamo uses the `DynamoFormat` type class to define how to read and write
different types to DynamoDB. Scanamo provides such formats for many common
types, but it's also possible to define a serialisation format for types
which Scanamo doesn't provide. For example to store Joda `DateTime` objects
as ISO `String`s in Dynamo:

```tut:silent
import org.joda.time._
import com.gu.scanamo._
import com.gu.scanamo.syntax._
case class Foo(dateTime: DateTime)
val client = LocalDynamoDB.client()
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType._
LocalDynamoDB.createTable(client)("foo")('dateTime -> S)
```
```tut:book
implicit val jodaStringFormat = DynamoFormat.coercedXmap[DateTime, String, IllegalArgumentException](
DateTime.parse(_).withZone(DateTimeZone.UTC)
)(
_.toString
)
val fooTable = Table[Foo]("foo")
val operations = for {
_ <- fooTable.put(Foo(new DateTime(0)))
results <- fooTable.scan()
} yield results
Scanamo.exec(client)(operations).toList
```
48 changes: 48 additions & 0 deletions src/main/tut/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
layout: home
section: home
position: 1
---

[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.gu/scanamo_2.11/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.gu/scanamo_2.12) [![Build Status](https://travis-ci.org/guardian/scanamo.svg?branch=master)](https://travis-ci.org/guardian/scanamo) [![Coverage Status](https://coveralls.io/repos/github/guardian/scanamo/badge.svg?branch=master)](https://coveralls.io/github/guardian/scanamo?branch=master) [![Chat on gitter](https://badges.gitter.im/guardian/scanamo.svg)](https://gitter.im/guardian/scanamo)

Scanamo is a library to make using [DynamoDB](https://aws.amazon.com/documentation/dynamodb/) with Scala
simpler and less error-prone.

The main focus is on making it easier to avoid mistakes and typos by leveraging Scala's type system and some
higher level abstractions.

Quick start
-----------

Scanamo is published for Scala 2.11 and 2.12 to Maven Central, so just add the following to your `build.sbt`:

```scala
libraryDependencies ++= Seq(
"com.gu" %% "scanamo" % "0.8.1"
)
```

then, given a table and some case classes

```tut:silent
import com.gu.scanamo._
import com.gu.scanamo.syntax._
val client = LocalDynamoDB.client()
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType._
val farmersTableResult = LocalDynamoDB.createTable(client)("farmer")('name -> S)
case class Farm(animals: List[String])
case class Farmer(name: String, age: Long, farm: Farm)
```
we can simply `put` and `get` items from Dynamo, without boilerplate or reflection

```tut:book
val table = Table[Farmer]("farmer")
Scanamo.exec(client)(table.put(Farmer("McDonald", 156L, Farm(List("sheep", "cow")))))
Scanamo.exec(client)(table.get('name -> "McDonald"))
```

Licensed under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0).
34 changes: 34 additions & 0 deletions src/main/tut/put-get.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
layout: docs
title: Putting and Getting
position: 2
---

### Putting and Getting

Often when using DynamoDB, the primary use case is simply putting objects into
Dynamo and subsequently retrieving them:

```tut:silent
import com.gu.scanamo._
import com.gu.scanamo.syntax._
val client = LocalDynamoDB.client()
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType._
LocalDynamoDB.createTable(client)("muppets")('name -> S)
case class Muppet(name: String, species: String)
```
```tut:book
val muppets = Table[Muppet]("muppets")
val operations = for {
_ <- muppets.put(Muppet("Kermit", "Frog"))
_ <- muppets.put(Muppet("Cookie Monster", "Monster"))
_ <- muppets.put(Muppet("Miss Piggy", "Pig"))
kermit <- muppets.get('name -> "Kermit")
} yield kermit
Scanamo.exec(client)(operations)
```

Note that when using `Table` no operations are actually executed against DynamoDB until `exec` is called.
33 changes: 33 additions & 0 deletions src/main/tut/querying.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
layout: docs
title: Querying
position: 4
---

### Querying

Scanamo can be used to perform most queries that can be made against DynamoDB

```tut:silent
import com.gu.scanamo._
import com.gu.scanamo.syntax._
val client = LocalDynamoDB.client()
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType._
LocalDynamoDB.createTable(client)("transports")('mode -> S, 'line -> S)
case class Transport(mode: String, line: String)
val transportTable = Table[Transport]("transports")
val operations = for {
_ <- transportTable.putAll(Set(
Transport("Underground", "Circle"),
Transport("Underground", "Metropolitan"),
Transport("Underground", "Central")
))
tubesStartingWithC <- transportTable.query('mode -> "Underground" and ('line beginsWith "C"))
} yield tubesStartingWithC.toList
```
```tut:book
Scanamo.exec(client)(operations)
```

36 changes: 36 additions & 0 deletions src/main/tut/scanning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
layout: docs
title: Scanning
position: 3
---

### Scanning

If you want to go through all elements of a table, or index, Scanamo
supports scanning it:

```tut:silent
import com.gu.scanamo._
import com.gu.scanamo.syntax._
val client = LocalDynamoDB.client()
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType._
LocalDynamoDB.createTable(client)("lines")('mode -> S, 'line -> S)
case class Transport(mode: String, line: String)
```
```tut:book
val transportTable = Table[Transport]("lines")
val operations = for {
_ <- transportTable.putAll(Set(
Transport("Underground", "Circle"),
Transport("Underground", "Metropolitan"),
Transport("Underground", "Central"),
Transport("Tram", "Croydon Tramlink")
))
allLines <- transportTable.scan()
} yield allLines.toList
Scanamo.exec(client)(operations)
```

Loading

0 comments on commit 7cce578

Please sign in to comment.