リクエストパラメータにIDが指定押されているかどうかに応じて以下の処理を行います。

  • リクエストパラメータにIDなし ⇒ 新規登録画面を表示します。
  • リクエストパラメータにIDあり ⇒ USERSテーブルを検索し、該当のユーザ情報を初期表示した編集画面を表示します。

フォーム

画面からの入力値を受け取るためのFormをコントローラに定義します。Formは必ずしもコントローラに定義する必要はないのですが、コントローラでの処理に強く依存するため特に理由がない限りコントローラ内に定義するとよいでしょう。

まず、UserControllerの冒頭に以下のインポート文を追加します。これでFormの定義や基本的なバリデーションができるようになります。

import play.api.data._
import play.api.data.Forms._

登録・編集画面からの入力値を受け取るためのFormを定義します。

object UserController extends Controller {

  // フォームの値を格納する
  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)
  )

  ...

POINT

  • FormはStrutsのアクションフォームのようなものです
  • マッピングに従ってバリデーション(後述)が行われます

ビュー

続いてviews.userパッケージにedit.scala.htmlを実装します。引数にはFormのインスタンスと、プルダウンで選択する会社情報を格納したListを受け取ります。

@(userForm: Form[controllers.UserController.UserForm], companies: List[models.Tables.CompaniesRow])

@* テンプレートで利用可能なヘルパーをインポート *@
@import helper._

@main("ユーザ作成") {

  @* IDがある場合は更新処理、ない場合は登録処理を呼ぶ *@
  @form(userForm("id").value.map(x => routes.UserController.update).getOrElse(routes.UserController.create), 'class -> "container", 'role -> "form") {
    <fieldset>
      <div class="form-group">
        @inputText(userForm("name"), '_label -> "名前")
      </div>
      <div class="form-group">
        @select(userForm("companyId"), companies.map(x => x.id.toString -> x.name).toSeq, '_label -> "会社", '_default -> "-- 会社名を選択してください --")
      </div>
      @* IDがある場合(更新の場合)のみhiddenを出力する *@
      @userForm("id").value.map { value =>
        <input type="hidden" name="id" value="@value" />
      }
      <div>
        <input type="submit" value="保存" class="btn btn-success">
      </div>
    </fieldset>
  }

}

POINT

  • テンプレートでも@importでインポート文を記述することができます
  • @import helper._でPlayが提供する標準ヘルパー(フォームなどを出力する関数)を使用できるようになります

コントローラ

最後にUserControllereditメソッドを実装します。引数idが指定されていた場合は空のForm、指定されていた場合はForm#fillメソッドでFormに初期表示する値をセットしたうえでテンプレートを呼び出すようにします。

def edit(id: Option[Long]) = DBAction { implicit rs =>
  // リクエストパラメータにIDが存在する場合
  val form = if(id.isDefined) {
    // IDからユーザ情報を1件取得
    val user = Users.filter(_.id === id.get.bind).first

    // 値をフォームに詰める
    userForm.fill(UserForm(Some(user.id), user.name, user.companyId))
  } else {
    // リクエストパラメータにIDが存在しない場合
    userForm
  }

  // 会社一覧を取得
  val companies = Companies.sortBy(t => t.id).list

  Ok(views.html.user.edit(form, companies))
}

POINT

  • Scalaでは、if式は値を返します(ブロックの最後に評価した値がif式の戻り値になります)

上記のコードでは以下の記述で会社情報の一覧を取得しています。

val companies = Companies.sortBy(t => t.id).list

これは以下のSQLと同じ意味になります。

SELECT * FROM COMPANIES ORDER BY ID

実行

ここまで実装したらブラウザで一覧画面から新規作成やユーザ名のリンクをクリックし、以下のように登録画面と編集画面が表示されることを確認します。

ユーザ登録画面

ユーザ編集画面