I'm brand new to Play!, and I'm trying to migrate my existing website from cakePHP to Play!.
The problem I'm facing is about form validation.
I defined a case class User, representing the users of my website :
case class User(
val id: Long,
val username: String,
val password: String,
val email: String
val created: Date)
(There are some more fields, but these ones suffice to explain my problem)
I would like my users to be able to create an account on my website, using a form, and I would like this form to be validated by Play!.
So, I created the following action :
def register = Action {
implicit request =>
val userForm = Form(
mapping(
"id" -> longNumber,
"username" -> nonEmptyText(8),
"password" -> nonEmptyText(5),
"email" -> email,
"created" -> date)(User.apply)(User.unapply))
val processedForm = userForm.bindFromRequest
processedForm.fold(hasErrors => BadRequest("Invalid submission"), success => {
Ok("Account registered.")
})
}
Obviously, I do not want the user to fill the id or the creation date by himself in the form. So my question is : what should I do ?
Should I define a new "transition model" containing only the fields that are actually provided to the user in the form, and transform this intermediary model into the complete one before inserting it into my database ?
That is, replace my action by something like that :
def register = Action {
implicit request =>
case class UserRegister(
username: String,
password: String,
email: String)
val userForm = Form(
mapping(
"username" -> nonEmptyText(8),
"password" -> nonEmptyText(8),
"email" -> email)(UserRegister.apply)(UserRegister.unapply)
val processedForm = userForm.bindFromRequest
processedForm.fold(hasErrors => BadRequest("Invalid submission"), success => {
val user = User(nextID, success.username, success.password, success.email, new Date())
// Register the user...
Ok("Account created")
}
Or is there another, cleaner way to do what I want ?
I've been through many tutorials and the book "Play for Scala", but in the only examples that I found, the models were fully filled by the forms... I really like Play! so far, but it looks like the documentation often lacks examples...
Thank you very much for your answers !
You have a few choices:
Firstly, you could make the id
and created
fields Option[Long]
and Option[Date]
respectively. Then use a mapping like:
val userForm = Form(
mapping(
"id" -> optional(longNumber),
"username" -> nonEmptyText(8),
"password" -> nonEmptyText(5),
"email" -> email,
"created" -> optional(date)
)(User.apply)(User.unapply)
)
That would, I think, be logical, since a User
with a None
id would indicate that it has not yet been saved. This works well when you want to use the same form mapping to update an existing record.
Alternately, you can use ignored
mappings with some arbitrary placeholder data:
val userForm = Form(
mapping(
"id" -> ignored(-1L),
"username" -> nonEmptyText(8),
"password" -> nonEmptyText(5),
"email" -> email,
"created" -> ignored(new Date)
)(User.apply)(User.unapply)
)
This is not so good when reusing the form for update operations!
Finally, don't forget that your form mappings are bound/filled by functions that turn a tuple into an object, and an object into a tuple respectively. It's just a convenient convention to use the case class User.apply
and User.unapply
methods since these do just that. You could write alternative factory methods on your User
object to handle form instantiation:
object User {
def formApply(username: String, password: String, email: String): User =
new User(-1L, username, password, email, new Date)
def formUnapply(user: User): Option[(String,String,String)] =
Some((user.username, user.password, user.email))
}
And then user those in the Form object:
val userForm = Form(
mapping(
"username" -> nonEmptyText(8),
"password" -> nonEmptyText(5),
"email" -> email
)(User.formApply)(User.formUnapply)
)
Also, it's worth noting that the Scala forms documentation is about to get much better in 2.2.1 (and in fact it might already have rolled out here).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With