libro
www.tuyano.com
初心者のためのPlay Framework入門

Model(モデル)を使ってデータベースアクセスする[Scala編] (7/7)

作成:2013-02-10 10:25
更新:2013-02-10 10:25

■[応用] モデルとフォームのクラスを併用する

ここで作成したMydataクラスでは、namemailtelといった値が用意されていました。が、改めて作ったテーブルを見てみましょう。この他に「id」という項目もありましたね? プライマリキーであり、自動的に値が割り付けられるように設定した項目です。値は自動設定されますから、フォームで送信することもありませんから不要といえば不要です。

ただし、データの更新や削除などを行おうとすると、処理する対象のレコードはプライマリキー(ここではid)で識別するのが基本となります。そのためにも、idまで項目を含んだモデルにした方がいいでしょう。

ただし! そうすると、今度はFormとモデルで互換性がなくなります。idは自動設定されますから入力フォームを用意するわけにもいきません。idまで用意すると、Formにフォーム情報をバインドしたりすることが難しくなります。

このように、「実際のテーブルと、そのテーブルのデータを扱うためのフォームで項目などが違っている場合」の対処というのはけっこう必要になります。いろいろなやり方があるでしょうが、ここでは「テーブル保管用のモデルクラスと、フォーム保管用のクラスをそれぞれ用意して対処する」ということを行なってみましょう。

下のリスト欄に、モデル(mydata.scala)とコントローラー(Appllication.scala)のソースコードを掲載しておきます。これでIDまで含めてモデルを扱えるようになります。

●モデルでのIDの扱い
モデルクラスであるMydataでは、以下のような項目が引数に追加されるようになりました。
id: Pk[Long] = NotAssigned
PkというのはAnormのクラスで、IDを管理するための特別な値として用意されています。Pk[Long]というのは、値がLongのIDということを示します。その後のNotAssignedは、文字通り値が設定されないことを示します。

●フォーム用クラス
もう1つ、新たに追加されたのが「MydataForm」というクラスです。これがフォームの値を管理するためのものになります。以下の様なシンプルなcase classです。
case class MydataForm(name : String, 
        mail: String, tel: String)
3つの値がそのまま引数にあります。メソッドとしては、MydataFormからMydataを取得する「getMydata」メソッドを用意してあります。これは以下のようなシンプルな処理を行うだけのものです。
return Mydata(null, this.name, this.mail, this.tel)
Mydataを作成しreturnしています。第1引数(Pk[Long]の値)にはnullを指定してあります。これでMydataFormから、その値を移したMydataが取り出せるようになりました。ではsendformを修正部分を見てみましょう。
var myform = form1.bindFromRequest
val mydataform: MydataForm = myform.get
val mydata = mydataform.getMydata
val result = mydata.addData
Formインスタンスをform1に設定している部分では、(MydataForm.apply)(MydataForm.unapply)というようにバインドするクラスをMydataからMydataFormに変更しています。これで、bindFromRequestFormを取得し、getMydataFormとして情報が得られるようになります。ここからgetMydataMydataインスタンスが取り出されます。後は、そのaddDataを呼び出すだけです。


Scalaでは、モデルの機能を手作りしていく感覚でコーディングをしていくことになりますが、考えようによっては「モデルといっても入れ物だけ、実際のデータベースアクセス処理はコントローラーにてんこ盛り」といった形骸化されたモデルを作ることはないでしょう。案外、このほうがMVCの分離としては有益なのかも……?

※プログラムリストが表示されない場合

AddBlockなどの広告ブロックツールがONになっていると、プログラムリスト等が表示されない場合があります。これらのツールをOFFにしてみてください。

●プログラム・リスト●

※Mydata.scala

package models

import play.api.db._
import anorm._
import play.api.Play.current
import anorm.SqlParser._ 

case class Mydata(
    id: Pk[Long] = NotAssigned,
    name: String,
    mail: String,
    tel: String) {

    def addData {
        DB.withConnection { implicit c =>
            val id: Int = SQL("insert into mydatas (name, mail, tel) values ({name}, {mail}, {tel})").
            on('name->this.name, 'mail -> this.mail,
                'tel -> this.tel).executeUpdate()
        }
    }
}

object Mydata {
    val data = {
        get [anorm.Pk[Long]]("id") ~
        get[String]("name") ~
        get[String]("mail") ~
        get[String]("tel") map {
            case id ~ name ~ mail ~ tel => 
                Mydata(id, name, mail, tel)
        }
    }
    
    def getAll: List[Mydata] = {
        DB.withConnection { implicit c =>
            val datas = SQL("Select * from mydatas").
                as(Mydata.data *)
            return datas
        }
    }
}

case class MydataForm(name : String, mail: String, 
        tel: String) {
    
    def getMydata:Mydata = {
        return Mydata(null, this.name, this.mail, this.tel)
    }
}


※Application.scala

package controllers

import models._
import play.api._
import play.api.mvc._
import play.api.data._
import play.api.data.Form
import play.api.data.Forms._

object Application extends Controller {

    val form1 = Form(
         mapping(
            "name" -> text,
            "mail" -> text,
            "tel" -> text
        )(MydataForm.apply)(MydataForm.unapply)
    )
    
    def index = Action {
        val title = "サンプルページ"
        val msg = "サンプルのページです。"
        val datas = Mydata.getAll
        Ok(views.html.index(title, msg, form1, datas))
    }
    
    def sendform = Action { implicit request =>
        var myform = form1.bindFromRequest
        val mydataform: MydataForm = myform.get
        val mydata = mydataform.getMydata
        val result = mydata.addData
        val title = "サンプルページ"
        val msg = "名前:" + mydata.name + ", メール:" + mydata.mail
        Ok(views.html.index(title, msg, myform, null))
    }
}


※index.scala.htmlは変わらず

※関連コンテンツ

「初心者のためのPlay Framework入門」に戻る