Skip to content

Iterable's Utilities for Play Framework for Scala

License

Notifications You must be signed in to change notification settings

Iterable/iterable-play-utils

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

46 Commits

Repository files navigation

iterable-play-utils

Travis CIMaven

A collection of utilites used by Iterable in Scala Play! projects.

Adding to your SBT project

The latest version supports Play 2.8.x. To include it in your dependencies:

libraryDependencies +="com.iterable"%%"iterableplayutils"%"4.0.0"

All versions can be found on maven central.

VersionScala versionPlay! version
4.0.02.13.x/2.12.x2.8.x
3.0.02.13.x/2.12.x2.7.x
2.0.02.12.x/2.11.x2.6.x
1.1.12.11.x2.5.x
1.1.02.11.x2.4.x
1.0.12.10.x2.2.x

Automatic Case Class Mappings (via runtime reflection)

See com.iterable.play.utils.CaseClassMapping. Uses runtime reflection to generate form mappings for case classes without all the manual typing.

Once again, this uses runtime reflection, not compile-time macros.

Suppose you have the following case class:

caseclassFoo( bar: String, baz: Option[Long] )

In order to use forms/mappings, you would normally do:

valfooForm=Form( mapping( "bar"-> text, "baz"-> optional(longNumber) )(Foo.apply)(Foo.unapply) )

This works fine, but it can get very cumbersome if your case classes take many parameters. It's also difficult to keep track of things if you rename the various arguments. CaseClassMapping seeks to take care of this by automatically generating a Mapping[T] for your case class T. In order to use it, any non-standard types that your case class uses must expose an implicit Mapping[T] of that type in their companion object; additionally, that mapping must be either a nullary def or a val.

For example, to create a form for our example case class Foo, you can do:

valfooForm=Form(CaseClassMapping.mapping[Foo])

...and that's it!

More often we use it like this:

objectFoo{implicitvalmapping=CaseClassMapping.mapping[Foo] } // somewhere later where we need a Form[Foo]valfooForm=Form(implicitly[Mapping[Foo]])

If you want to add constraints to your mapping, you can still do so; for example, if we want to make sure that Foo.bar is at least 5 characters long:

objectFoo{implicitvalmappingWithConstraint=CaseClassMapping.mapping[Foo].verifying{Constraint[Foo]("Foo.bar"){foo =>Constraints.minLength(5)(foo.bar) } } }

Another use case for this is for posting form data via Play's WS. Normally, you would do something like this:

WS.url("https://some.api.expecting.form.encoded.data").post( Map( "name"->Seq("ilya"), "age"->Seq(9001.toString), "email"->Seq("ilya at iterable dot com"), "favoriteBands"->Seq("Judas Priest", "Accept") ) )

That doesn't look particularly nice... so you can use UnbindableToWsRequest:

caseclassUser(name: String, age: Int, email: String, favoriteBands: Seq[String]) extendsUnbindableToWsRequest[User] objectUser{implicitvalmapping=CaseClassMapping.mapping[User] } valuser=User(name ="ilya", age =9001, email ="ilya at iterable dot com", favoriteBands =Seq("Judas Priest", "Accept")) WS.url("some url").post(user.unbindToWsRequest)

Note that there is one caveat with this; Seq types. Using the previous example, the unbound data will look like this:

Map( "name"->Seq("ilya"), "age"->Seq(9001.toString), "email"->Seq("ilya at iterable dot com"), "favoriteBands[0]"->Seq("Judas Priest"), "favoriteBands[1]"->Seq("Accept") )

Specifically, note that favoriteBands is unbound as

"favoriteBands[0]"->Seq("Judas Priest"), "favoriteBands[1]"->Seq("Accept")

instead of

"favoriteBands"->Seq("Judas Priest", "Accept")

See the tests for more sample usage.

About

Iterable's Utilities for Play Framework for Scala

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 5

Languages