Skip to content
This repository has been archived by the owner on Jun 15, 2020. It is now read-only.

Commit

Permalink
Merge pull request #60 from OlivierBlanvillain/doc-and-co
Browse files Browse the repository at this point in the history
Revert unlifted, add Release Notes
  • Loading branch information
jto committed Jun 1, 2016
2 parents a240a45 + 9a9bad8 commit 96d46ab
Show file tree
Hide file tree
Showing 29 changed files with 295 additions and 454 deletions.
156 changes: 25 additions & 131 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# The unified data validation library

[![Travis](https://api.travis-ci.org/jto/validation.png?branch=master)](https://travis-ci.org/jto/validation) [![Maven](https://img.shields.io/maven-central/v/io.github.jto/validation-core_2.11.svg)](https://maven-badges.herokuapp.com/maven-central/io.github.jto/validation-core_2.11) [![Scala.js](https://www.scala-js.org/assets/badges/scalajs-0.6.8.svg)](https://www.scala-js.org) [![Gitter](https://badges.gitter.im/jto/validation.svg)](https://gitter.im/jto/validation?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Coverage Status](https://coveralls.io/repos/github/jto/validation/badge.svg?branch=v2.0)](https://coveralls.io/github/jto/validation?branch=v2.0)
[![Travis](https://api.travis-ci.org/jto/validation.png?branch=master)](https://travis-ci.org/jto/validation) [![Coverage Status](https://coveralls.io/repos/github/jto/validation/badge.svg?branch=v2.0)](https://coveralls.io/github/jto/validation?branch=v2.0) [![Maven](https://img.shields.io/maven-central/v/io.github.jto/validation-core_2.11.svg)](https://maven-badges.herokuapp.com/maven-central/io.github.jto/validation-core_2.11) [![Scala.js](https://www.scala-js.org/assets/badges/scalajs-0.6.8.svg)](https://www.scala-js.org) [![Gitter](https://badges.gitter.im/jto/validation.svg)](https://gitter.im/jto/validation?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)


## Overview

Expand Down Expand Up @@ -40,163 +40,58 @@ It's also a unification of play's [Form Validation API](https://www.playframewor

Being based on the same concepts as play's Json validation API, it should feel very similar to any developer already working with it. The unified validation API is, rather than a totally new design, a simple generalization of those concepts.


## Design

The unified validation API is designed around a core defined in package `play.api.data.mapping`, and "extensions". Each extension provides primitives to validate and serialize data from / to a particular format ([Json](documentation/tut/ScalaValidationJson.md), [form encoded request body](documentation/tut/ScalaValidationMigrationForm.md), etc.). See [the extensions documentation](documentation/tut/ScalaValidationExtensions.md) for more information.
The unified validation API is designed around a core defined in package `play.api.data.mapping`, and "extensions". Each extension provides primitives to validate and serialize data from / to a particular format ([Json](http://jto.github.io/validation/docs/book/ScalaValidationJson.html), [form encoded request body](http://jto.github.io/validation/docs/book/ScalaValidationMigrationForm.html), etc.). See [the extensions documentation](http://jto.github.io/validation/docs/book/ScalaValidationExtensions.html) for more information.

To learn more about data validation, please consult [Validation and transformation with Rule](documentation/tut/ScalaValidationRule.md), for data serialization read [Serialization with Write](documentation/tut/ScalaValidationWrite.md). If you just want to figure all this out by yourself, please see the [Cookbook](documentation/tut/ScalaValidationCookbook.md).

## Using the validation api in your project

### 2.x branch

Add the following lines in your `build.sbt`

```scala
resolvers += Resolver.sonatypeRepo("releases")

// If you want only the core
libraryDependencies += "io.github.jto" %% "validation-core" % "2.0.0"

// Json validation based on play-json AST (optional)
libraryDependencies += "io.github.jto" %% "validation-playjson" % "2.0.0"

// Json validation based on json4s AST (optional)
libraryDependencies += "io.github.jto" %% "validation-json4s" % "2.0.0"

// Form validation (optional)
libraryDependencies += "io.github.jto" %% "validation-form" % "2.0.0"

// CSV validation (optional)
libraryDependencies += "io.github.jto" %% "validation-delimited" % "2.0.0"

// XML validation (optional)
libraryDependencies += "io.github.jto" %% "validation-xml" % "2.0.0"
```

### 1.x branch *(deprecated)*
## Using the validation api in your project

Add the following lines in your `build.sbt`
Add the following dependencies your `build.sbt` as needed:

```scala
resolvers += Resolver.sonatypeRepo("releases")

// If you want only the core
libraryDependencies += "io.github.jto" %% "validation-core" % "1.1"
val validationVersion = "2.0"

// Json validation
libraryDependencies += "io.github.jto" %% "validation-json" % "1.1"

// Form validation
libraryDependencies += "io.github.jto" %% "validation-form" % "1.1"

// ...
```

## Validation 2.0.0

### Release note

- TODO: @olivier

### 1.x -> 2.x Migration guide

Version 2.x breaks back compatibility with the 1.x version. The migration has been tested on production code making heavy use of validation for json (based on play-json) and xml. Even for big project, migrating to 2.x should not take more than 30 min.

The best method is just to update validation in your dependencies, and let the compiler figure out what's broken. The following changes list should cover everything needed.

#### Build file.

The project name for play-json based validation has changed.

```scala
"io.github.jto" %% "validation-json" % validationVersion
libraryDependencies ++= Seq(
"io.github.jto" %% "validation-core" % validationVersion,
"io.github.jto" %% "validation-playjson" % validationVersion,
"io.github.jto" %% "validation-json4s" % validationVersion,
"io.github.jto" %% "validation-form" % validationVersion,
"io.github.jto" %% "validation-delimited" % validationVersion,
"io.github.jto" %% "validation-xml" % validationVersion
)
```

becomes

```scala
"io.github.jto" %% "validation-playjson" % validationVersion
```

#### Package name

- Since the library does not depends on Play anymore, and is not planned to be integrated into Play, the package names have changed. Basically `play.api.mapping` now becomes `jto.validation`. A simple search and replace in your project should work.
- The validation api support both json4s and play-json. Therefore, the package name for play json changes. `play.api.mapping.json` becomes `play.api.mapping.playjson`

#### Rule renaming

The following `Rule` and `Write` were renamed to better match the naming convention in all subprojects.

- `Rules.jodaDate` becomes `Rules.jodaDateR`
- `Writes.jodaDate` becomes `Writes.jodaDateW`

If you encounter implicit resolution problem, you probably have a name clash. Make sure none of your `Rule` / `Write` uses those names.

#### unlift

Since validation does not uses play-functional anymore, all the uses of `unlift` calls should disappear. We recommend you use the `unlifted` method directly.

For example the following code:

```scala
implicit lazy val w3: Write[User1, UrlFormEncoded] = To[UrlFormEncoded]{ __ =>
((__ \ "name").write[String] ~
(__ \ "friend").write[Option[User1]])(unlift(User1.unapply _))
}
```

becomes

```scala
implicit lazy val w3: Write[User1, UrlFormEncoded] = To[UrlFormEncoded]{ __ =>
((__ \ "name").write[String] ~
(__ \ "friend").write[Option[User1]]).unlifted(User1.unapply)
}
```

The same method is also available on `Format` so

```scala
lazy val w: Format[JsValue, JsObject, RecUser] = Formatting[JsValue, JsObject]{ __ =>
((__ \ "name").format[String] ~
(__ \ "friends").format(seqR(w), seqW(w)))(RecUser.apply _, unlift(RecUser.unapply _))
}
```
becomes

```scala
lazy val w: Format[JsValue, JsObject, RecUser] = Formatting[JsValue, JsObject]{ __ =>
((__ \ "name").format[String] ~
(__ \ "friends").format(seqR(w), seqW(w))).unlifted(RecUser.apply _, RecUser.unapply)
}
```


#### ValidationError

Since we removed all the dependencies on Play, `play.api.mapping.ValidationError` is re-defined in validation. If you're using this class, make sure to replace it by `jto.validation.ValidationError`.

## Play dependencies

- For playjson, the 2.0.0 version depends on play 2.5.3.
- 1.1.X versions are built with play 2.4
- if you are using play 2.3 you need to use the 1.0.2 version.
| Validation | Play |
| ---------- | ----- |
| 2.0 | 2.5.3 |
| 1.1.x | 2.4.x |
| 1.0.2 | 2.3.x |


## Documentation

[Documentation is here](http://jto.github.io/validation/docs/book/)

- [Validating and transforming data](http://jto.github.io/validation/docs/book/ScalaValidationRule.html)
- [Combining Rules](http://jto.github.io/validation/docs/book/ScalaValidationRuleCombinators.html)
- [Validation Inception](http://jto.github.io/validation/docs/book/ScalaValidationMacros.html)
- [Validating Json](http://jto.github.io/validation/docs/book/ScalaValidationJson.html)
- [Serializing data with Write](http://jto.github.io/validation/docs/book/ScalaValidationWrite.html)
- [Combining Writes](http://jto.github.io/validation/docs/book/ScalaValidationWriteCombinators.html)
- [Validation Inception](http://jto.github.io/validation/docs/book/ScalaValidationMacros.html)
- [Play's Form API migration](http://jto.github.io/validation/docs/book/ScalaValidationMigrationForm.html)
- [Play's Json API migration](http://jto.github.io/validation/docs/book/ScalaValidationMigrationJson.html)
- [Extensions: Supporting new types](http://jto.github.io/validation/docs/book/ScalaValidationExtensions.html)
- [Exporting Validations to Javascript using Scala.js](http://jto.github.io/validation/docs/book/ScalaJsValidation.html)
- [Cookbook](http://jto.github.io/validation/docs/book/ScalaValidationCookbook.html)
- [Release notes](http://jto.github.io/validation/docs/book/ReleaseNotes.html)
- [v2.0 Migration guide](http://jto.github.io/validation/docs/book/V2MigrationGuide.html)

## Contributors

Expand All @@ -207,4 +102,3 @@ Since we removed all the dependencies on Play, `play.api.mapping.ValidationError
- Arthur Gautier - https://github.com/baloo
- Jacques B - https://github.com/Timshel
- Alexandre Tamborrino - https://github.com/atamborrino
- Olivier Blanvillain - https://github.com/OlivierBlanvillain
2 changes: 1 addition & 1 deletion docs/src/main/tut/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# The Play data validation library
# [The Play data validation library](https://github.com/jto/validation)

## Overview

Expand Down
11 changes: 11 additions & 0 deletions docs/src/main/tut/ReleaseNotes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Release notes

### 2.0:

- Replace `play/functional` with `typelevel/cats` ([#38](https://github.com/jto/validation/pull/38) [1](https://github.com/jto/validation/commit/49110067caea0a483f840ad2334ad05ae379f1cf), [2](https://github.com/jto/validation/commit/a9108a00cbef8b6de668bfb7c7bee44c1b974537), [3](https://github.com/jto/validation/commit/5ccc7895672412da189f4e9efbea97ce7be467be), [4](https://github.com/jto/validation/commit/0ebcd973e24a33f87d280fc8565419d8ad8b9829), [5](https://github.com/jto/validation/commit/6505afe98972f8cf3b356f334db2a9a39b806961), [6](https://github.com/jto/validation/commit/b5aacbe711e59a7fe35d55ec1a63d0b633646ddc), [7](https://github.com/jto/validation/commit/cbe0d5b0310038840af3e1f6fa5668963ae32773), [8](https://github.com/jto/validation/commit/09aca48b858afb20845c21bf7e25faf2ad611cc7), [9](https://github.com/jto/validation/commit/86f63d0cc547d41c6dce36e2877d5b0de8a8cbac))

- Impove error reporting ([#40](https://github.com/jto/validation/pull/40) [1](https://github.com/jto/validation/commit/357b87778f19fbbc06a49da08cb2dccf9e0a40e3), [2](https://github.com/jto/validation/commit/c1bdac7fcff098b1d85c6881c731d5fd4ee2ac2e))

- Rework project structure: `json``playjson`, `json4s``json-ast`, `jsjson` ([#50](https://github.com/jto/validation/pull/50) [0](https://github.com/jto/validation/commit/f95ac30b1d1346a27e26c08841ee06c00340891f) [1](https://github.com/jto/validation/commit/5b36f606334a5fe26715cf0d7c47ebf861acb811), [2](https://github.com/jto/validation/commit/3f31f4917d01b8f6fdefe4adaca70ddc823722db))

- Add Scala.js support ([#42](https://github.com/jto/validation/pull/42) [1](https://github.com/jto/validation/commit/db359abfbe90d2b3b853beabcbabe88ecd1cfddb), [2](https://github.com/jto/validation/commit/568aa1fa1df06d775abb583cac8da679c1301227), [3](https://github.com/jto/validation/commit/d67d6dee7d99d27d6cf751cc69b83235b57a8246), [4](https://github.com/jto/validation/commit/67499a823ff463860b72d6697cf45b5764c475b2), [5](https://github.com/jto/validation/commit/d720ba265541a90f225c388043b5430a68e9fff3))
29 changes: 18 additions & 11 deletions docs/src/main/tut/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
- [Validating and transforming data](ScalaValidationRule.md)
- [Combining Rules](ScalaValidationRuleCombinators.md)
- [Validation Inception](ScalaValidationMacros.md)
- [Validating Json](ScalaValidationJson.md)
- [Serializing data with Write](ScalaValidationWrite.md)
- [Combining Writes](ScalaValidationWriteCombinators.md)
- [Play's Form API migration](ScalaValidationMigrationForm.md)
- [Play's Json API migration](ScalaValidationMigrationJson.md)
- [Extensions: Supporting new types](ScalaValidationExtensions.md)
- [Exporting Validations to Javascript using Scala.js](ScalaJsValidation.md)
- [Cookbook](ScalaValidationCookbook.md)
- Features

- [Validating and transforming data](ScalaValidationRule.md)
- [Combining Rules](ScalaValidationRuleCombinators.md)
- [Serializing data with Write](ScalaValidationWrite.md)
- [Combining Writes](ScalaValidationWriteCombinators.md)
- [Validation Inception](ScalaValidationMacros.md)
- [Exporting Validations to Javascript using Scala.js](ScalaJsValidation.md)
- [Extensions: Supporting new types](ScalaValidationExtensions.md)
- [Cookbook](ScalaValidationCookbook.md)

- Migration

- [v2.0 Migration guide](V2MigrationGuide.md)
- [Play's Form API migration](ScalaValidationMigrationForm.md)
- [Play's Json API migration](ScalaValidationMigrationJson.md)

- [Release notes](ReleaseNotes.md)
6 changes: 3 additions & 3 deletions docs/src/main/tut/ScalaJsValidation.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
def cat(path: String): Unit =
println(scala.io.Source.fromFile(s"play-scalajs-example/$path").mkString.trim)
```
Validation 2.0 supports Scala.js, which allows compiling validation logic for JavaScript to run it directly in the browser. Let's begin by playing with it. Try to change the `tryMe` variable in the following editor. The result is automatically output.
Validation 2.0 supports Scala.js, which allows compiling validation logic for JavaScript to run it directly in the browser. Let's begin by playing with it. Try to change the `tryMe` variable in the following editor. The result is automatically outputted.

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.15.2/codemirror.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.15.2/codemirror.min.js"></script>
Expand Down Expand Up @@ -90,7 +90,7 @@ client.Validate().user(tryMe);
})()
</script>

Using validation from Scala.js is no different than any other scala library. There is however some friction to intergration Scala.js into an existing Play + JavaScript, which we try to adress in this document. Assuming no prior knowledge on Scala.js, we explain how to cross compiled and integrate validation logic into an existing Play/JavaScript application.
Using validation from Scala.js is no different than any other scala library. There is, however, some friction to integrate Scala.js into an existing Play + JavaScript, which we try to address in this document. Assuming no prior knowledge on Scala.js, we explain how to cross compiled and integrate validation logic into an existing Play/JavaScript application.

You will first need to add two sbt plugins, Scala.js itself and `sbt-play-scalajs` to make it Scala.js and Play coexist nicely:

Expand Down Expand Up @@ -144,4 +144,4 @@ As an example, we create a simple view with a textarea which validates it's cont
cat("jvm/app/views/index.scala.html")
```

This complete example is available in a [separate repository](https://github.com/OlivierBlanvillain/play-scalajs-validation-example). The example at the begining of this page was generated with Play in production mode, which fully optimizes the output of Scala.js compilation using the Google Closure Compiler, resulting a binary file under 100KB gzipped.
This complete code of this example is available in the [play-scalajs-example](https://github.com/jto/validation/tree/v2.0/play-scalajs-example) sub project. The binary used to power the editor at the beginning of this page was generated by running Play in production mode, which fully optimizes the output of Scala.js compilation using the Google Closure Compiler to obtain a final .js file under 100KB gzipped.
27 changes: 14 additions & 13 deletions docs/src/main/tut/ScalaValidationCookbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ case class Creature(
isDead: Boolean,
weight: Float)
implicit val creatureRule = From[JsValue]{ __ =>
implicit val creatureRule: Rule[JsValue, Creature] = From[JsValue] { __ =>
import jto.validation.playjson.Rules._
((__ \ "name").read[String] ~
(__ \ "isDead").read[Boolean] ~
(__ \ "weight").read[Float]) (Creature.apply _)
(__ \ "weight").read[Float])(Creature.apply)
}
```
```tut
Expand All @@ -40,7 +40,7 @@ A common example of this use case is the validation of `password` and `password
import jto.validation._
import play.api.libs.json._
val passRule = From[JsValue] { __ =>
val passRule: Rule[JsValue, String] = From[JsValue] { __ =>
import jto.validation.playjson.Rules._
// This code creates a `Rule[JsValue, (String, String)]` each of of the String must be non-empty
((__ \ "password").read(notEmpty) ~
Expand Down Expand Up @@ -72,7 +72,7 @@ When validating recursive types:
- Use the `lazy` keyword to allow forward reference.
- As with any recursive definition, the type of the `Rule` **must** be explicitly given.

```tut
```tut:silent
case class User(
name: String,
age: Int,
Expand All @@ -81,19 +81,19 @@ case class User(
friend: Option[User])
```

```tut
```tut:silent
import jto.validation._
import play.api.libs.json._
// Note the lazy keyword, and the explicit typing
// Note the lazy keyword
implicit lazy val userRule: Rule[JsValue, User] = From[JsValue] { __ =>
import jto.validation.playjson.Rules._
((__ \ "name").read[String] ~
(__ \ "age").read[Int] ~
(__ \ "email").read[Option[String]] ~
(__ \ "isAlive").read[Boolean] ~
(__ \ "friend").read[Option[User]]) (User.apply _)
(__ \ "friend").read[Option[User]])(User.apply)
}
```

Expand Down Expand Up @@ -123,10 +123,10 @@ val js = Json.parse("""
}
""")
val r = From[JsValue] { __ =>
val r: Rule[JsValue, Seq[(String, String)]] = From[JsValue] { __ =>
import jto.validation.playjson.Rules._
val tupleR = Rule.fromMapping[JsValue, (String, String)] {
val tupleR: Rule[JsValue, (String, String)] = Rule.fromMapping[JsValue, (String, String)] {
case JsObject(Seq((key, JsString(value)))) => Valid(key.toString -> value)
case _ => Invalid(Seq(ValidationError("BAAAM")))
}
Expand All @@ -142,7 +142,7 @@ r.validate(js)

Consider the following class definitions:

```tut
```tut:silent
trait A
case class B(foo: Int) extends A
case class C(bar: Int) extends A
Expand Down Expand Up @@ -181,7 +181,7 @@ rule.validate(e)
```tut:silent
val typeInvalid = Invalid(Seq(Path -> Seq(ValidationError("validation.unknownType"))))
val rule = From[JsValue] { __ =>
val rule: Rule[JsValue, A] = From[JsValue] { __ =>
import jto.validation.playjson.Rules._
(__ \ "name").read[String].flatMap[A] {
case "B" => (__ \ "foo").read[Int].map(B.apply _)
Expand All @@ -203,6 +203,7 @@ rule.validate(e)
```tut:silent
import jto.validation._
import play.api.libs.json._
import scala.Function.unlift
case class Creature(
name: String,
Expand All @@ -213,7 +214,7 @@ implicit val creatureWrite = To[JsObject] { __ =>
import jto.validation.playjson.Writes._
((__ \ "name").write[String] ~
(__ \ "isDead").write[Boolean] ~
(__ \ "weight").write[Float]).unlifted(Creature.unapply)
(__ \ "weight").write[Float])(unlift(Creature.unapply))
}
```
```tut
Expand All @@ -232,7 +233,7 @@ implicit val latLongWrite = {
import jto.validation.playjson.Writes._
To[JsObject] { __ =>
((__ \ "lat").write[Float] ~
(__ \ "long").write[Float]).unlifted(LatLong.unapply)
(__ \ "long").write[Float])(unlift(LatLong.unapply))
}
}
Expand Down
Loading

0 comments on commit 96d46ab

Please sign in to comment.