Converting Pk[Long] to Option[Long] in a Form - scala

I have been having trouble understanding what the issue is here since the Scala Anorm Pk became deprecated.
I switched my model to the following:
case class Item(id: Option[Long] = NotAssigned,
title: String,
descr: String,
created: Option[Date],
private val imgs: List[Img],
private val tags: List[Tag])
From id: Pk[Long]
I changed my form to:
val itemForm = Form(
mapping(
"id" -> ignored(23L),
"title" -> nonEmptyText,
"descr" -> nonEmptyText,
"created" -> optional(ignored(new Date)),
"imgs" -> Forms.list(itemImgs),
"tags" -> Forms.list(itemTags)
)(Item.apply)(Item.unapply)
)
From "id" -> ignored(NotAssigned:Pk[Long])
But, I get this error.
type mismatch; found : (Option[Long], String, String, scala.math.BigDecimal, Option[java.util.Date], List[models.Img], List[models.Tag]) => models.Item required: (Long, String, String, Option[java.util.Date], List[models.Img], List[models.Tag]) => ?
)(Item.apply)(Item.unapply)
Why is an Option[Long] not required on the Item model?
I don't know what 23L is, but that's what was in the Play Documentation. The value of id in the database is coming from a sequence.
If I change it to:
"id" -> ignored(NotAssigned:Option[Long]),
Which makes the most sense to me... I get this error:
type mismatch; found : anorm.NotAssigned.type required: Option[Long]
"id" -> ignored(NotAssigned:Option[Long]),
Which makes less sense than before.

Just to clarify, it's not Anorm that's deprecated, but the Pk type within Anorm.
Your problem here is that you're trying to assign NotAssigned to an Option[Long], which is incompatible. You should change all of the NotAssigneds to None.
So your class would look like this:
case class Item(
id: Option[Long] = None,
title: String,
descr: String,
price: BigDecimal,
created: Option[Date],
private val imgs: List[Img],
private val tags: List[Tag]
)
And the Form mapping:
"id" -> ignored[Option[Long]](None)

Related

How to convert List[String] to List[Object] in Scala

I need to change from one List[String] to List[MyObject] in scala.
For example,JSON input is like below
employee: {
name: "test",
employeeBranch: ["CSE", "IT", "ECE"]
}
Output should be like this,
Employee: {
Name: "test",
EmployeeBranch:[{"branch": "CSE"}, {"branch": "IT"}, {"branch": "ECE"}]
}
Input case class:
Class Office(
name: Option[String],
employeeBranch: Option[List[String]])
Output case class:
Class Output(
Name: Option[String],
EmployeeBranch: Option[List[Branch]])
case class Branch(
branch: Option[String])
This is the requirement.
It is hard to answer without knowing details of the particular JSON library, but an Object is probably represented as a Map. So to convert a List[String] to a List[Map[String, String]] you can do this:
val list = List("CSE", "IT", "ECE")
val map = list.map(x => Map("branch" -> x))
This gives
List(Map(branch -> CSE), Map(branch -> IT), Map(branch -> ECE))
which should convert to the JSON you want.

anorm joda-time - localdatetime support

With Anorm 2.5.2
SQL(s"insert into user (name, registered_date) values ({name},{registered_date})").on(
'name -> user.name,
'registered_date -> user.registeredDate
).executeInsert()
Compilation error:
Error:(72, 24) type mismatch; found : (Symbol,
org.joda.time.LocalDateTime) required: anorm.NamedParameter
'registered_date -> user.registeredDate
Should I include some implicit Time->Row transformation or it should come out of the box with anorm?
where user:
case class User(id: Option[Long] = None,
name: String,
registeredDate: LocalDateTime // joda-time'
)
import anorm.JodaParameterMetaData._
from here: https://groups.google.com/forum/#!topic/play-framework/I6TnTzO5MUw
(it was nice talking to myself :) )

Scala, create a form with more than 22 fields

I'm using scala and Play framework and i want create a form with more than 22 fields so I share my field in 3 tuple like that:
val firstMapping = tuple(
"f1" -> text, "f2" -> text, ... "f18" -> text
)
val secondMapping = tuple(
"f19" -> text, "20"-> text ... "f25" -> text
)
val thirdMapping = tuple(
"f26" -> text, ... "f29" -> text
)
So after I regroup them in a form:
val createForm = From(tuple(
"general" -> firstMapping,
"specific" -> secondMapping,
"more_specific" -> thirdMapping
))
I think this is the good solution, but my question is about the view file (i'm in a MVC architecture)
In that view I want to pass my form like that:
#(formCreate: Form[])
But I don't know what I need to put in the " [] " (I'm french I don't know wath is the word for that in english) and how to create my field in HTML ?
Usually I use that kind html form:
#helper.form() {
<input type="text" name="id_metier" id="id_metier" maxlength="255"/>
}
So can I use that kind of field again or I need to use specific field from Play framework ? And what are the parameter for that #(formCreate: Form[]) ?
Thank you for your help
Your form is of type Tuple3 with some other tuples inside. Painful to read, write, use, maintain.
Form[((String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String), (String, String, String, String, String, String, String), (String, String, String, String))]
Refer to the docs: https://www.playframework.com/documentation/2.5.x/ScalaForms
and just create a case class that will contain 3 nested case classes for your data, name fields appropriately.
Here is the example from docs for nested case class
case class AddressData(street: String, city: String)
case class UserAddressData(name: String, address: AddressData)
val userFormNested: Form[UserAddressData] = Form(
mapping(
"name" -> text,
"address" -> mapping(
"street" -> text,
"city" -> text
)(AddressData.apply)(AddressData.unapply)
)(UserAddressData.apply)(UserAddressData.unapply)
)
When creating form you refer to nested fields with . notation
#helper.inputText(userFormNested("name"))
#helper.inputText(userFormNested("address.street"))
#helper.inputText(userFormNested("address.city"))

scala play form how handle java bigdecimal

I try to fill a form with the values of System
def edit(id: Long) = IsAuthenticated { username => implicit request =>
User.findByEmail(username).map { user =>
System.findById(id).map { system =>
Ok(html.systems.editForm(id, systemForm.fill(system), Person.options, user))
}.getOrElse(NotFound)
}.getOrElse(Forbidden)
}
but some of 'system' values are java.math.BigDecimal
val systemForm = Form(
mapping(
"id" -> ignored(NotAssigned:Pk[BigDecimal]),
"sys_name" -> nonEmptyText,
"sys_desc" -> nonEmptyText,
"sys_owner1_id" -> longNumber,
"sys_owner2_id" -> optional(longNumber)
)(System.apply)(System.unapply)
)
and it says :
type mismatch; found : (anorm.Pk[java.math.BigDecimal], String, String, String, Option[String], java.math.BigDecimal, Option[java.math.BigDecimal]) => models.System required: (anorm.Pk[java.math.BigDecimal], String, String, Long, Option[Long]) => ?
how can i handle this?
Looks like problem in anorm or somewhere near.
As you may see from error description sys_owner1_id and sys_owner2_id are BigIntegers in query result, but declared as long in form.
I am not familiar with anorm, but solution is to declare these ids as long in anorm, or declare them as BigInteger in form mapping or convert from BigInteger to long in your query.

Play Forms from case classes

I'm new to playframework. I have my model for a User as well as the accompanying object for the static methods...
case class User(id: Int, username: String, password: String, fullname: String, /
lastLogin : Date, updatedOn: Date, updatedBy: Int, createdOn: Date, createdBy: Int)
I want to create a form for this class omitting some of the details. Currently I have a UserForm case class
case class UserForm(fullName:String, username: String, password:String, confirm:String)
To allow me to use:
val userForm = Form(
mapping(
"fullName" -> of[String],
"username" -> of[String],
"password" -> of[String],
"confirm" -> of[String]
)(UserForm.apply)(UserForm.unapply)
)
This feels kind of Hacker-ish. Is there an idiomatic and more conscice way to do this?
How about
val userForm = Form(
mapping(
"fullName" -> text,
"username" -> text,
"password" -> text,
"confirm" -> text
)(UserForm.apply)(UserForm.unapply)
)
There are a lot more built-in checks and validations. The basics are listed here: http://www.playframework.com/documentation/2.1.0/ScalaForms
If you don't need them in an object you could use a tuple
val userForm = Form(
tuple(
"fullName" -> text,
"username" -> text,
"password" -> text,
"confirm" -> text
)
)
The tuple in your case you have the following type: (String, String, String, String) which you could use like this: val (fullName, username, password, confirm) = refToTuple
Late coming to this, but I just released a utility to help with this! Using your classes, your code would look like this:
case class User(id: Int, username: String, password: String, fullname: String, lastLogin : Date, updatedOn: Date, updatedBy: Int, createdOn: Date, createdBy: Int)
object User { implicit val mapping = CaseClassMapping.mapping[User] }
val userForm = Form(implicitly[Mapping[User]])
You can find the source and instructions for including it in your project on github: https://github.com/Iterable/iterable-play-utils