novamage / svalidator-play   3.0.0

MIT License GitHub

A plugin adapter to integrate svalidator with the play framework

Scala versions: 2.13 2.12

svalidator-play

An integration library for the SValidator validation library with the Play! framework

You may see this library in action in the svalidator-play-sample application

Installation

svalidator-play is available on Maven for scala 2.12. Just add the following line to your build.sbt:

libraryDependencies += "com.github.novamage" % "svalidator-play_2.12" % "2.3.0"

svalidator-play transitively depends on svalidator, so it's not necessary to add both to your project.

Prerequisites

It is necessary to read the documentation of SValidator before reading this documentation. Also, it is assumed that you are familiarized with how the Play! framework operates.

Usage

svalidator-play provides the classes PlayBindingValidator and PlayMappingBindingValidator to adapt the regular BindingValidator and MappingBindingValidator functionalities with Play! framework's Request. Additionally, you may use PlayBindingValidatorWithData and PlayMappingBindingValidatorWithData if you'd like to store some type of data along with the validation result. The PlayBindingValidator provides the following four methods:

  def bindFromRequest(implicit request: Request[?]): BindingAndValidationWithData[A, Nothing]

def bindLocalized(implicit messagesRequest: MessagesRequest[?]): BindingAndValidationWithData[A, Nothing]

def extractFromRequest(implicit request: Request[?],
                       extractor: PlayRequestValuesMapExtractor): BindingAndValidationWithData[A, Nothing]

def extractLocalized(implicit messagesRequest: MessagesRequest[?],
                     extractor: PlayRequestValuesMapExtractor): BindingAndValidationWithData[A, Nothing]

The bindFromRequest method will take the received request and map the values in the body and the queryString into a values map of type Map[String, Seq[String]] to pass into the regular bindAndValidate method of BindingValidator.

The bindLocalized will do the same as above, and in addition, will call the localize method in the resulting BindingAndValidationSummary, passing the messagesRequest.messages.apply method as the function that performs the localization for you (this is Play's default way of localization)

By default, the operation of the extracting the values from the request into the values map is performed by the DefaultPlayRequestExtractor, which you can see here:

package com.github.novamage.svalidator.play.binding

import play.api.mvc.{AnyContentAsFormUrlEncoded, Request}

object DefaultPlayRequestExtractor extends PlayRequestExtractor {

 override def extractValuesMapFromRequest(request: Request[?]): Map[String, Seq[String]] = {
  val queryString = request.queryString
  val formUrlEncodedBody = request.body match {
   case AnyContentAsFormUrlEncoded(data) => data
   case _ => Map.empty[String, Seq[String]]
  }
  val allKeys = queryString.keySet ++ formUrlEncodedBody.keySet
  allKeys.map { key =>
   key -> (formUrlEncodedBody.getOrElse(key, Nil) ++ queryString.getOrElse(key, Nil))
  }.toMap
 }

 override def extractBindingMetadataFromRequest(request: Request[?]): Map[String, Any] = Map.empty

}

In short, it takes all keys from both an url encoded body and the query string, and puts all of the values in the resulting values map, concatenating the lists of values for matching keys if necessary.

However, if you'd like to customize the way that the values are extracted from the request, or append metadata to be passed to the binders later on, you may call instead the methods extractFromRequest and extractLocalized. These methods will implicitly receive a PlayRequestExtractor, which you may provide to fully customize the way values and metadata are extracted from the request.

Finally, the PlayMappingBindingValidator works in a similar to the PlayBindingValidator, with the only difference being that, just like the regular MappingBindingValidator, it allows you to pass a TypeTag[B] and a mapOperation: B => A to bind the request into a specific type of object and then apply the conversion function to transform the bound object into something else for validation. It has the same four methods as PlayBindingValidator, so you may choose to perform regular binding, localized binding, or either of them with a custom extractor.