2013-10-27 7 views
6

私はPlay!の新しいです!私はcakePHPからPlay!へ私の既存のウェブサイトを移行しようとしています!Playでフォームを正しく検証する方法スカラ?

私が直面している問題はフォームの検証です。

私は私のウェブサイトのユーザーを表す、ケースクラスのユーザーを定義した:

case class User(
    val id: Long, 
    val username: String, 
    val password: String, 
    val email: String 
    val created: Date) 

(そこにいくつかのより多くのフィールドがありますが、これらのものは私の問題を説明するのに十分)

私は私のユーザーを希望フォームを使用して自分のウェブサイトにアカウントを作成できるようにするため、このフォームをPlay!によって検証することができます。

だから、私は次のアクションを作成:明らか

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.") 
    }) 
} 

を、私は、ユーザーがフォームに自分でIDや作成日を記入する必要はありません。だから私の質問は:私は何をすべきですか?

実際にフォームにユーザーに提供されるフィールドのみを含む新しい「移行モデル」を定義し、この中間モデルを完全なものに変換してからデータベースに挿入する必要がありますか?

そのようなことで、私の行動を置き換える、次のとおりです。

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") 
} 

または別の、私が欲しいものを行うためのクリーンな方法がありますか?

私は多くのチュートリアルと "Play for Scala"の本を読んできましたが、私が見つけた唯一の例では、モデルは完全にフォームで埋められていました...私は本当にPlayが好きです!これまでのところ、ドキュメントには例がないようです。

ありがとうございました!あなたは、いくつかの選択肢があり

+1

私は、あなたが記述したどんな種類の移行モデルも使用しません。したがって、ユーザー登録フォームの例では、User.create関数が無視するため、idフィールドは何でもかまいません。 (データベースの自動増分)。私は自分のユーザー編集フォーム(作成と同じフォーム)と同じことをしますが、そこでは認証システムを使用してフォームバインディングの後にIDを検証します。 –

答えて

4

:まず

を、あなたはそれぞれidcreatedフィールドOption[Long]Option[Date]を作ることができます。 None IDを持つUserは、それがまだ保存されていないことを示すであろうから、私は、論理的、と思うだろう

val userForm = Form(
    mapping(
    "id" -> optional(longNumber), 
    "username" -> nonEmptyText(8), 
    "password" -> nonEmptyText(5), 
    "email" -> email, 
    "created" -> optional(date) 
)(User.apply)(User.unapply) 
) 

:その後のようなマッピングを使用しています。これは、同じフォームマッピングを使用して既存のレコードを更新する場合にうまく機能します。

代わりに、あなたはいくつかの任意のプレースホルダデータをignoredマッピングを使用することができます。

val userForm = Form(
    mapping(
    "id" -> ignored(-1L), 
    "username" -> nonEmptyText(8), 
    "password" -> nonEmptyText(5), 
    "email" -> email, 
    "created" -> ignored(new Date) 
)(User.apply)(User.unapply) 
) 

更新操作のためにフォームを再利用する際にこれはあまりよくないです!

最後に、フォームマッピングが関数によってバインド/フィルされ、タプルをオブジェクトに変換し、オブジェクトをタプルに変換することを忘れないでください。ケースクラスUser.applyと​​のメソッドを使うのは便利な慣習です。あなたは、フォームのインスタンス化を処理するために、あなたのUserオブジェクトの代替ファクトリメソッドを書くことができます:

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)) 
} 

し、ユーザーフォームオブジェクトのもの:

val userForm = Form(
    mapping(
    "username" -> nonEmptyText(8), 
    "password" -> nonEmptyText(5), 
    "email" -> email 
)(User.formApply)(User.formUnapply) 
) 

をまた、それはScalaのフォームのドキュメントを約あることは注目に値します2.2.1でもっと良くなっています(実際には、すでにhereが公開されている可能性があります)。

+0

非常に詳細な回答をいただきありがとうございます!私は特にapply/unapply関数を使用するソリューションが好きです。適用のような機能をいくつか持たせるのは悪い習慣ですか、それとも私はまだ何かが欠けていますか? (いくつかの機能によって、私は2〜3を意味します...) – Martin

+0

@Martin:なぜそれが悪い習慣になるかは考えられません。さまざまな方法でクラスのインスタンスを構築する[コンパニオンオブジェクト](http://daily-scala.blogspot.co.uk/2009/09/companion-object.html)のファクトリメソッドは完全に有効です。 – Mikesname

関連する問題