Permalink
Browse files

Enum support for Play Framework 2

  • Loading branch information...
leon committed May 22, 2012
0 parents commit f9759c916c0e4210aaf60176c5382c2f4ef21e47
@@ -0,0 +1,7 @@
+.*
+!.gitignore
+!.travis.yml
+target/
+project/project
+project/target
+tmp
@@ -0,0 +1,6 @@
+language: scala
+scala:
+ - 2.9.1
+
+notifications:
+ email: false
@@ -0,0 +1,32 @@
+# Scala enumerationeration plugin for Play Framework 2
+This plugin makes it possible to use enumerations across Play Framework 2
+
+ * Forms
+ * JSON
+
+Possibly in future
+
+ * Path
+ * QueryString
+ * Javascript literal
+
+If I can figure out how... a bit over my head at the moment of writing. please feel free to send me a pullrequest with a solution :)
+
+[![Build Status](https://secure.travis-ci.org/leon/play-enumeration.png)](http://travis-ci.org/leon/play-enumeration)
+
+### Installation
+Ddding the plugin to your `project/Build.scala`
+
+ val appDependencies = Seq(
+ "se.radley" %% "play-plugins-enumeration" % "<add latest version here>"
+ )
+
+## Path
+
+## QueryString
+
+## Javascript
+
+## Forms
+
+## JSON
@@ -0,0 +1,3 @@
+# v1.0
+
+ * First draft of plugin.
@@ -0,0 +1 @@
+seq(lsSettings:_*)
@@ -0,0 +1,50 @@
+import sbt._
+import sbt.Keys._
+
+object ProjectBuild extends Build {
+
+ lazy val buildVersion = "1.0.0-SNAPSHOT"
+
+ lazy val root = Project(id = "play-plugins-enumeration", base = file("."), settings = Project.defaultSettings).settings(
+ organization := "se.radley",
+ description := "Scala Enumeration plugin for PlayFramework 2",
+ version := buildVersion,
+ scalaVersion := "2.9.1",
+ resolvers += "Typesafe Releases" at "http://repo.typesafe.com/typesafe/releases/",
+ resolvers += "Typesafe Snapshots" at "http://repo.typesafe.com/typesafe/snapshots/",
+ libraryDependencies += "play" %% "play" % "2.0.1",
+ libraryDependencies += "play" %% "play-test" % "2.0.1" % "test",
+
+ publishMavenStyle := true,
+ publishArtifact in Test := false,
+ pomIncludeRepository := { _ => false },
+ pomExtra := (
+ <url>http://github.com/leon/play-enumeration</url>
+ <licenses>
+ <license>
+ <name>Apache 2.0</name>
+ <url>http://www.opensource.org/licenses/Apache-2.0</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+ <scm>
+ <url>git@github.com:leon/play-enumeration.git</url>
+ <connection>scm:git:git@github.com:leon/play-enumeration.git</connection>
+ </scm>
+ <developers>
+ <developer>
+ <id>leon</id>
+ <name>Leon Radley</name>
+ <url>http://leon.radley.se</url>
+ </developer>
+ </developers>
+ ),
+ publishTo <<= version { version: String =>
+ val nexus = "https://oss.sonatype.org/"
+ if (version.trim.endsWith("SNAPSHOT"))
+ Some("snapshots" at nexus + "content/repositories/snapshots")
+ else
+ Some("releases" at nexus + "service/local/staging/deploy/maven2")
+ }
+ )
+}
@@ -0,0 +1,12 @@
+resolvers ++= Seq(
+ "sbt-idea-repo" at "http://mpeltonen.github.com/maven/",
+ "less is" at "http://repo.lessis.me",
+ "coda" at "http://repo.codahale.com",
+ Resolver.url("sbt-plugin-releases", new URL("http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases/"))(Resolver.ivyStylePatterns)
+)
+
+addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.0.0")
+
+addSbtPlugin("com.jsuereth" % "xsbt-gpg-plugin" % "0.6")
+
+addSbtPlugin("me.lessis" % "ls-sbt" % "0.1.1")
@@ -0,0 +1,22 @@
+
+{
+ "organization":"se.radley",
+ "name":"play-plugins-enumeration",
+ "version":"1.0.0",
+ "description":"Scala Enumeration plugin for PlayFramework 2",
+ "site":"http://github.com/leon/play-enumeration",
+ "tags":["scala", "enum", "enumeration", "play"],
+ "docs":"http://github.com/leon/play-enumeration",
+ "licenses": [{
+ "name": "Apache 2.0",
+ "url": "http://www.opensource.org/licenses/Apache-2.0"
+ }],
+ "resolvers": ["https://oss.sonatype.org/content/groups/public/"],
+ "dependencies": [{
+ "organization":"play",
+ "name": "play",
+ "version": "[2.0,)"
+ }],
+ "scalas": ["2.9.1"],
+ "sbt": false
+}
@@ -0,0 +1 @@
+error.enum=Invalid value
@@ -0,0 +1,35 @@
+package se.radley.plugin.enumeration
+
+import play.api.mvc._
+import play.api.data.format.Formatter
+import play.api.data.{FormError, Forms, Mapping}
+
+package object form {
+
+ /**
+ * Constructs a simple mapping for a text field (mapped as `scala.Enumeration`)
+ *
+ * For example:
+ * {{{
+ * Form("status" -> enum(Status))
+ * }}}
+ *
+ * @param enum the Enumeration#Value
+ */
+ def enum[E <: Enumeration](enum: E): Mapping[E#Value] = Forms.of(enumFormat(enum))
+
+ /**
+ * Default formatter for `scala.Enumeration`
+ *
+ */
+ def enumFormat[E <: Enumeration](enum: E): Formatter[E#Value] = new Formatter[E#Value] {
+ def bind(key: String, data: Map[String, String]) = {
+ play.api.data.format.Formats.stringFormat.bind(key, data).right.flatMap { s =>
+ scala.util.control.Exception.allCatch[E#Value]
+ .either(enum.withName(s))
+ .left.map(e => Seq(FormError(key, "error.enum", Nil)))
+ }
+ }
+ def unbind(key: String, value: E#Value) = Map(key -> value.toString)
+ }
+}
@@ -0,0 +1,27 @@
+package se.radley.plugin.enumeration
+
+import play.api.mvc._
+import play.api.data.format.Formatter
+import play.api.libs.json.{Writes, JsString, JsValue, Reads}
+
+package object json {
+ /**
+ * Deserializer for Enumeration types.
+ *
+ * {{{
+ * (Json \ "status").as(enum(Status))
+ * }}}
+ */
+ def enum[E <: Enumeration](enum: E): Reads[E#Value] = new Reads[E#Value] {
+ def reads(json: JsValue) = json match {
+ case JsString(s) => {
+ try {
+ enum.withName(s)
+ } catch {
+ case _ => throw new RuntimeException("Enumeration expected")
+ }
+ }
+ case _ => throw new RuntimeException("String expected")
+ }
+ }
+}
@@ -0,0 +1,3 @@
+package se.radley.plugin
+
+package object enumeration {}
@@ -0,0 +1,45 @@
+package se.radley.plugin.enumeration
+
+import org.specs2.mutable.Specification
+import play.api._
+import play.api.mvc._
+import play.api.test._
+import play.api.test.Helpers._
+import java.io.File
+import play.api.Play.current
+import play.api.libs.json._
+import play.api.libs.json.Json._
+import play.api.libs.json.Generic._
+
+object EnumSpec extends Specification {
+
+ "Enumerations" should {
+ "Be bindable in a form" in {
+ import play.api.data._
+ import play.api.data.Forms._
+ import form.enum
+
+ object Status extends Enumeration {
+ val Free = Value("free")
+ val Busy = Value("busy")
+ }
+
+ val statusForm = Form("status" -> enum(Status))
+
+ val data = Map("status" -> "free")
+ statusForm.bind(data).get must equalTo(Status.Free)
+ }
+
+ "Serialize and deserialize to JSON" in {
+ import json.enum
+ object Status extends Enumeration {
+ val Free = Value("free")
+ }
+
+ val e = Status.Free
+ val m = Map("status" -> e.toString)
+ val jsonM = toJson(m)
+ (jsonM \ "status").as(enum(Status)) must equalTo(e)
+ }
+ }
+}

0 comments on commit f9759c9

Please sign in to comment.