Skip to content

Instantly share code, notes, and snippets.

View dsugden's full-sized avatar

Dave Sugden dsugden

  • Shopify
  • Gatineau
View GitHub Profile
@dsugden
dsugden / FooRoute.scala
Created September 1, 2014 12:49
Spray Routes with API versioning
/**
* Foo restful interface.
*/
trait FooRoute extends HttpService with AskSupport {
import examples.FooProtocol._
import examples.FooProtocolV2._
implicit val timeout: Timeout
implicit val fooActorPath: ActorPath
import org.json4s.{DefaultFormats, Formats}
object Json4sProtocol extends Json4sSupport {
implicit def json4sFormats: Formats = DefaultFormats
}
@dsugden
dsugden / FooProtocolV2.scala
Created September 1, 2014 12:42
Marshalling with ContentTypes
/**
* FooProtocol v2
*/
object FooProtocolV2 {
sealed trait FooActorMessage
case class HelloFoo(hi: String, there:String) extends FooActorMessage
case class FooResponse(helloBackTo: String) extends FooActorMessage
import examples.Json4sProtocol._
@dsugden
dsugden / FooProtocol.scala
Created September 1, 2014 12:38
Marshalling with ContentTypes
/**
* FooProtocol v1
*/
object FooProtocol {
sealed trait FooActorMessage
case class HelloFoo(hi: String) extends FooActorMessage
case class FooResponse(helloBackTo: String) extends FooActorMessage
import Json4sProtocol._
import org.json4s.native.Serialization.{read,write => swrite}
@dsugden
dsugden / gist:ce018faada463e1e19e6
Created September 1, 2014 12:22
Spray Custom Media Types
/**
* Foo Version Media Types for v1 and v2
*/
object VersionMediaTypes{
lazy val `application/vnd.ww.v2.foo+json` =
MediaTypes.register(MediaType.custom("application/vnd.ww.v2.foo+json"))
lazy val `application/vnd.ww.v1.foo+json` =
MediaTypes.register(MediaType.custom("application/vnd.ww.v1.foo+json"))
}
@dsugden
dsugden / gist:b3db9008d156f7488ac6
Last active August 29, 2015 14:05
Accept Header example
GET /user/1 HTTP/1.1
Accept: application/vnd.company.app.user-v2+json
HTTP/1.1 200 OK
Content-Type: application/vnd.company.app.user-v2+json
{"user":
{"email":"bob@gmail.com"}
}
object UseScalaz {
def main(args: Array[String]): Unit = {
import scalaz._
case class Better(total: List[Int])
def sum(i:Int) = StateChange[Better,Int](s => Better.sum(i)(s))
// Lets run the sum computation, and add all the results together
def composeAddResultS(one:Int,two:Int,three:Int): StateChange[Better,Int] =
sum(one).doAgainWithNewState(
firstResult =>
sum(two).doAgainWithNewState( secondResult =>
sum(three).mapResult( thirdResult => firstResult + secondResult + thirdResult) ))
// we notice S => (S,A) is useful, almost composable and testable, but awkward... lets do better
// Lets create a type that wraps the computation, and add some useful combinators: mapResult, doAgainWithResultAndNewState
case class StateChange[S,A](run: S => (S,A)){
def mapResult[B](f:A => B):StateChange[S,B] = StateChange{ (s:S) =>
val(s2,a) = run(s)
(s2,f(a))
}
/*
// we desire this pattern Better => (Better,Int)
type BetterUpdate = Better => (Better,Int)
val firstF:BetterUpdate = Better.sum(1)
val secondF:BetterUpdate = Better.sum(2)
val thirdF:BetterUpdate = Better.sum(3)
// the external state is threaded through a sequence of computations