Play2.5-scalikejdbc2.5s

ユーザ登録・編集画面の実装

リクエストパラメータにIDが指定押されているかどうかに応じて以下の処理を行います。 リクエストパラメータにIDなし ⇒ 新規登録画面を表示します。 リクエストパラメータにIDあり ⇒ USERSテーブルを検索し、該当のユーザ情報を初期表示した編集画面を表示します。 フォーム 画面からの入力値を受け取るためのFormを定義します。Formは必ずしもコントローラに定義する必要はないのですが、コントローラでの処理に強く依存するため特に理由がない限りコントローラクラスのコンパニオンオブジェクトに定義するとよいでしょう。 ここではUserControllerと同じソースファイルに以下のようなコンパニオンオブジェクトを追加します。 object UserController { // フォームの値を格納するケースクラス case class UserForm(id: Option[Long], name: String, companyId: Option[Int]) // formから送信されたデータ ⇔ ケースクラスの変換を行う val userForm = Form( mapping( "id" -> optional(longNumber), "name" -> nonEmptyText(maxLength = 20), "companyId" -> optional(number) )(UserForm.apply)(UserForm.unapply) ) } コンパニオンオブジェクトとは、クラスやトレイトと同じファイル内に同じ名前で定義されたオブジェクトのことで、コンパニオンオブジェクトと対応するクラスやトレイトは互いにprivateなメンバーにアクセスできるなどの特徴があります。クラスやトレイトで使用する共通的なメソッドやクラス等を括り出したりするのに使います。 POINT コンパニオンオブジェクトとは、クラスと同じファイル内に同じ名前で定義されたオブジェクトのことです FormはStrutsのアクションフォームのようなものです マッピングに従ってバリデーション(後述)が行われます ビュー 続いてviews.userパッケージにedit.scala.htmlを実装します。引数にはFormのインスタンスと、プルダウンで選択する会社情報を格納したSeqを受け取ります。

ルーティングの定義

Bootstrapを使うための準備 sbt newコマンドで作成されたプロジェクトにはデフォルトのレイアウトテンプレートとしてapp/views/main.scala.htmlが生成されています。ここにBootstrapで使用するCSSとJavaScriptを追加します。 @(title: String)(content: Html) <!DOCTYPE html> <html> <head> <title>@title</title> <link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/main.css")"> <link rel="shortcut icon" type="image/png" href="@routes.Assets.versioned("images/favicon.png")"> <script src="@routes.Assets.versioned("javascripts/hello.js")" type="text/javascript"></script> @* ↓↓↓↓ここから追加↓↓↓↓ *@ <link rel="stylesheet" media="screen" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css"> <link rel="stylesheet" media="screen" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"> <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js" type="text/javascript"></script> @* ↑↑↑↑ここまで追加↑↑↑↑ *@ </head> <body> @content </body> </html> また、デフォルトではContent-Security-Policyヘッダがdefault-src 'self'を返すため上記で指定した外部CDNのCSSファイルやJavaScriptファイルを読み込むことができません。そこでconf/application.confに以下の設定を追加してContent-Security-Policyヘッダが出力されないようにしておきます。 play.filters.headers.contentSecurityPolicy=null コントローラの雛形を作る controllersパッケージにUserControllerクラスを以下のように作成します。 package controllers import play.

削除処理の実装

指定したIDのユーザをUSERSテーブルから削除し、一覧画面へリダイレクトします。 コントローラ すでに一覧画面に「削除」ボタンは表示されているので、そこから呼び出されるコントローラのメソッドのみ実装します。 def remove(id: Long) = Action { implicit request => DB.localTx { implicit session => // ユーザを削除 Users.find(id).foreach { user => Users.destroy(user) } // 一覧画面へリダイレクト Redirect(routes.UserController.list) } } ここでもscalikejdbcGenで自動生成されたUsers.destroy()メソッドを使用して削除処理を行っています。これをQueryDSLで書き直すと以下のようになります。 withSQL { delete.from(Users).where.eq(column.id, entity.id) }.update.apply() 実行 一覧画面から「削除」をクリックしてユーザ情報が削除されることを確認してください。

登録・更新処理の実装

入力値のバリデーションを行い、エラーの有無に応じて以下の処理を行います。 エラーあり ⇒ フォームにエラー情報をセットして入力フォームに戻ります。 エラーなし ⇒ DBへの登録・更新処理を行い、一覧画面へリダイレクトします。 コントローラ UserControllerのメソッドのうち、登録処理を行うcreateメソッドと更新処理を行うupdateメソッドを実装します。 入力フォームの値を受け取るには、userForm.bindFromRequestメソッドでリクエストの内容をFormにバインドし、foldメソッドでエラーがあった場合の処理と、OKの場合の処理を記述します。以下はcreateメソッドの実装例です。 def create = Action { implicit request => DB.localTx { implicit session => // リクエストの内容をバインド userForm.bindFromRequest.fold( // エラーの場合 error => { BadRequest(views.html.user.edit(error, Companies.findAll())) }, // OKの場合 form => { // ユーザを登録 Users.create(form.name, form.companyId) // 一覧画面へリダイレクト Redirect(routes.UserController.list) } ) } } updateメソッドも同じように実装します。 def update = Action { implicit request => DB.