How to Validate Negative BigDecimals in scala play Framework FORMS? - scala

I want to validate (do not allow) Negative amount values , in my POST Request
Following is my Validation trait which have Form mapping,
bigDecimal has precision and scale, but how to make sure of negative bigDecimals coming in the request?
trait BICValidation extends CommonValdidation {
implicit val bICForm = Form(
mapping(
"id" -> optional(number),
"name" -> text,
"description" -> optional(text),
"bId" -> optional(number),
"amount" -> bigDecimal
)(BIC.apply)(BIC.unapply)
)
}

Try
"amount" -> bigDecimal.verifying("amount must be negative", a => a < 0)
and see the docs.

Related

Sorting of list buffer scala

I have a ListBuffer of Maps in scala. All maps inside the buffer contain some keys. For example:
ListBuffer(
Map(
"date" -> 24092018,
"datetime" -> "24-09-2018 11:23:44",
"lat" -> "48.33"
),Map(
"date" -> 24092018,
"datetime" -> "24-09-2018 11:53:44",
"lat" -> "48.33"
),Map(
"date" -> 23092018,
"datetime" -> "23-09-2018 10:53:44",
"lat" -> "48.33"
)
)
I want to sort this ListBuffer based on datetime so that latest one will come first.
sortBy is a method of the object (and reverse too); Directly from the language reference:
def sortBy[B](f: (A) ⇒ B)(implicit ord: math.Ordering[B]): ListBuffer[A]
Sorts this Seq according to the Ordering which results from transforming an implicitly given Ordering with a transformation function.

Scala: Map Option[String] in tuple of Form Data and access it

I am using Scala Forms. I have set a keys and values in Form Data that is enclosed into a tuple having String as data type.
val userForm = Form(
tuple(
"k1" -> optional(v1),
"k2" -> optional(v2),
"k3" -> optional(v3)
)
)
and access this Form values using
val (k1, k2, k3) = userForm.bindFromRequest.get
It is working fine.
What I need is that. I want to make k2 and k3 keys as Option[String] type and k1 as normal String type. So, when I place Option[String] to k2, k3 keys.
val userForm = Form(
tuple(
"k1" -> optional(v1),
"k2" -> Some(optional(v2)),
"k3" -> Some(optional(v3))
)
)
It throws error -
type mismatch;
found : (String, Some[play.api.data.Mapping[Option[String]]])
required: (String, play.api.data.Mapping[?])
Any suggestions ?
Scala-Form provides you a way of making it so that you can have Option values via using its optional field type.
So... when you declare a form as,
val userForm = Form(
tuple(
"k1" -> optional(text),
"k2" -> optional(text),
"k3" -> optional(text)
)
)
Then, the userForm already declares the values k1, k2 and k3 to be Option[String].
So to have it your needed way, declare the form with k1 as normal text and others as option(text)
val userForm = Form(
tuple(
"k1" -> text,
"k2" -> optional(text),
"k3" -> optional(text)
)
)
A form mapping can also define optional values using Forms.optional:
case class UserOptionalData(name: String, email: Option[String])
val userFormOptional = Form(
mapping(
"name" -> text,
"email" -> optional(email)
)(UserOptionalData.apply)(UserOptionalData.unapply)
) //example taken from play docs
This maps to an Option[A] in output, which is None if no form value is found.
Change k1 from optional to text to make it a compulsory field. Make k1 text
val userForm = Form(
tuple(
"k1" -> text,
"k2" -> Some(optional(text)),
"k3" -> Some(optional(text))
)
)

Play framework Leon Salat Model Form Mapping

I'm creating a scala application using Play framework and mongoDB. I manage to have the connections up using Leon Play-Salat. I have a model
case class Person(
id: ObjectId = new ObjectId,
fname: String,
mname: String,
lname: String
)
In my controller I need to map it to a form
val personForm: Form[Person] = Form(
// Defines a mapping that will handle Contact values
mapping(
"id" -> of[ObjectId],
"fname" -> nonEmptyText,
"mname" -> text,
"lname" -> nonEmptyText
)(Person.apply)(Person.unapply))
How do I map the ObjectID to the form ? I'm getting error Object not found for the ObjectId.
Manage to get it working
val personForm: Form[Person] = Form(
// Defines a mapping that will handle Contact values
mapping(
"id" -> ignored(new ObjectId),
"fname" -> nonEmptyText,
"mname" -> text,
"lname" -> nonEmptyText
)(Person.apply)(Person.unapply))
I'm trying to do a CRUD function thus need the ID.
Found using own constructor and deconstructor is better
val personForm: Form[Person] = Form(
mapping(
"fname" -> nonEmptyText,
"mname" -> text,
"lname" -> nonEmptyText
)((fname, mname, lname) => Person(new ObjectId, fname, mname, lname))
((person: Person) => Some((person.fname, person.mname, person.lname))) )

Handling very long forms with Play 2

My application contain big form with 18 fields. It is processed with standard form mapping, like this:
val bigForm = Form(
mapping(
"id" -> of[ObjectId],
"title" -> text,
// And another 16 fields...
...
)
)
And all was well, but today I decided to add one more field and here comes the problem - mapping is not able to take more than 18 arguments.
What should I do then? I thinking of combining some fields into the structure, but additional structure requires additional formatter, JSON serializer and deserializer, too much work. I'm looking for a general solution, more fields are likely to appear in the future.
Another solution I'm thinking about is to handle form manually, without Form's.
Are there better solutions?
You can use nested mappings, e.g.
val bigForm = Form(
mapping(
"id" -> of[ObjectId],
"title" -> text,
"general" -> mapping(
...
)(GeneralInfo.apply)(GeneralInfo.unapply),
"advanced" -> mapping(
...
)(AdvancedInfo.apply)(AdvancedInfo.unapply)
)
)
Another possibility is using view objects and updating only the part that was submitted (e.g. via separate forms or AJAX):
val generalForm = Form(
mapping(
"title" -> text,
...
)
)
def updateGeneral(id: ObjectId) = Action { implicit request =>
MyObject.findById(id).map { myObj =>
generalForm.bindFromRequest.fold(
fail => BadRequest(...),
form => {
val newObj = myObj.copy(title = form.title, ...)
MyObject.save(newObj)
Ok(...)
}
)
}.getOrElse(NotFound)
}

Play 2.0 form - field "verifying" method is not a member

Practicing what is written here: ScalaForms, I have created the following form:
val personCreationForm = Form(
tuple (
"name" -> nonEmptyText,
"age" -> number verifying (min(0), max(100)) /*ERROR*/
) verifying ("Wrong entry", result => result match {
case (name, age) => true
})
)
However, the error on verifying states that value verifying is not a member of (java.lang.String, play.api.data.Mapping[Int]).
Working with mapping instead of tuple, as in the referenced example, makes no difference. What is wrong here?
According to Scala operators precedence rules, methods starting with a letter have a lower precedence than others so when you write:
"age" -> number verifying (min(0), max(100))
The compiler builds the following expression:
("age" -> number) verifying (min(0), max(100))
Which is not what you want! You can rewrite it as follows:
"age" -> number.verifying(min(0), max(100))
"age" -> (number verifying (min(0), max(100)))
And the current Play documentation is wrong. Thanks for catching it!