Skip to content

Instantly share code, notes, and snippets.

@gbougeard
Last active August 29, 2015 14:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gbougeard/153fba5bb6f8395c0f73 to your computer and use it in GitHub Desktop.
Save gbougeard/153fba5bb6f8395c0f73 to your computer and use it in GitHub Desktop.
sealed trait GHPayload
case class GHIssuePayload(...,...,...) extends GHPayload
case class GHPRPayload(...,...,...) extends GHPayload
case class GHPushPayload(...,...,...) extends GHPayload
// implicits rules defined with validation API for case classes..
val rule: Rule[JsValue, GHPayload] = From[JsValue] { __ =>
import play.api.data.mapping.json.Rules._
(__ \ "event").read[GHEvent].flatMap[GHPayload] {
case GHEvent.issues => path.read[JsValue, GHIssuePayload].fmap(GHIssuePayload.apply _)
case GHEvent.pull_request => path.read[JsValue, GHPRPayload].fmap(GHPRPayload.apply _)
case GHEvent.push => path.read[JsValue, GHPushPayload].fmap(GHPushPayload.apply _)
case _ => Rule(_ => typeFailure)
}
}
rule.validate(payload)
}
// ERROR
[error] /DATA/git/github-hooks/app/services/GHHandler.scala:44: type mismatch;
[error] found : (String, models.GHModels.GHIssue, models.GHModels.GHLabels, models.GHModels.GHRepo, models.GHModels.GHUser) => models.GHModels.GHIssuePayload
[error] required: models.GHModels.GHIssuePayload => models.GHModels.GHPayload
[error] case GHEvent.issues => path.read[JsValue, GHIssuePayload].fmap(GHIssuePayload.apply _)
[error] ^
[error] /DATA/git/github-hooks/app/services/GHHandler.scala:45: type mismatch;
[error] found : (String, Double, models.GHModels.GHPullRequest, models.GHModels.GHRepo, models.GHModels.GHUser) => models.GHModels.GHPRPayload
[error] required: models.GHModels.GHPRPayload => models.GHModels.GHPayload
[error] case GHEvent.pull_request => path.read[JsValue, GHPRPayload].fmap(GHPRPayload.apply _)
[error] ^
[error] /DATA/git/github-hooks/app/services/GHHandler.scala:46: type mismatch;
[error] found : (String, String, String, Boolean, Boolean, Boolean, Option[String], String, List[models.GHModels.GHCommits], models.GHModels.GHCommits, models.GHModels.GHRepo, models.GHModels.GHOwner, models.GHModels.GHSender) => models.GHModels.GHPushPayload
[error] required: models.GHModels.GHPushPayload => models.GHModels.GHPayload
[error] case GHEvent.push => path.read[JsValue, GHPushPayload].fmap(GHPushPayload.apply _)
[error] ^
[error] three errors found
sealed trait GHPayload
object GHPayload {
def apply(`class`: String, data: JsValue): GHPayload = {
import models.GHModelJson._
(`class` match {
case "GHIssuePayload" => From[JsValue, GHIssuePayload](data)(GHIssuePayloadJsonFormat)
case "GHPRPayload" => From[JsValue, GHPRPayload](data)(GHPRPayloadJsonFormat)
case "GHPushPayload" => From[JsValue, GHPushPayload](data)(GHPushPayloadJsonFormat)
}).get
}
}
def handle(payload: JsValue) = {
// play.Logger.debug(s"handle $e")
val path = Path \ "payload"
val typeFailure = Failure(Seq(Path -> Seq(ValidationError("validation.unknownType"))))
val rule: Rule[JsValue, GHPayload] = From[JsValue] { __ =>
import play.api.data.mapping.json.Rules._
import models.GHModelJson._
(__ \ "event").read[GHEvent].flatMap[GHPayload] {
case GHEvent.issues => (__ \ "payload").read[JsValue].fmap(GHPayload.apply("GHIssuePayload", _))
case GHEvent.pull_request => (__ \ "payload").read[JsValue].fmap(GHPayload.apply("GHPRPayload", _))
case GHEvent.push => (__ \ "payload").read[JsValue].fmap(GHPayload.apply("GHPushPayload", _))
case _ => Rule(_ => typeFailure)
}
}
rule.validate(payload)
}
// But if do
val js = Json.obj("event" -> "push", "payload" -> json) // with json not a push payload but e.g. an issue payload
handler.handle(js)
// => NoSuchElementException: : Failure.get in the GHPayload.apply
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment