Play Scala モデル追加
DB connectionができたので、次はモデルを記述して、
モデルからテーブルのレコードをCRUDできるようにする。
こちらの記事をまるっと参考にさせていただきました。
まずは昨日時点のevolutionファイルを修正する。
PostgreSQLでは大文字小文字が区別されないようなので、
テーブル名、カラム名を小文字で統一。
/conf/evolutions/default/1.sql
1 # --- !Ups 2 3 CREATE TABLE "user" ( 4 "username" TEXT NOT NULL, 5 "password" TEXT NOT NULL, 6 "name" TEXT NOT NULL 7 ); 8 9 CREATE TABLE "article" ( 10 "user_id" INT NOT NULL, 11 "content" TEXT NOT NULL 12 ); 13 14 CREATE TABLE "comment" ( 15 "user_id" INT NOT NULL, 16 "article_id" INT NOT NULL, 17 "content" TEXT NOT NULL 18 ); 19 20 # --- !Downs 21 22 DROP TABLE "user"; 23 DROP TABLE "article"; 24 DROP TABLE "comment";
次に各テーブルのモデルを定義する。
/app/models/Models.scala
1 package models 2 3 case class User(username: String, password: String, name: String) 4 case class Article(user_id: Int, content: String) 5 case class Comment(user_id: Int, article_id: Int, content: String)
モデルファイルがエンティティによって分かれていないのがちょっと不思議。
ファイルを別にすることもできると思いますがひとまず例に倣ってこれで。
DAOは下記のように記述。
/app/dao/UserDAO.scala
1 package dao 2 3 import scala.concurrent.Future 4 5 import javax.inject.Inject 6 import models.User 7 import play.api.db.slick.DatabaseConfigProvider 8 import play.api.db.slick.HasDatabaseConfigProvider 9 import play.api.libs.concurrent.Execution.Implicits.defaultContext 10 import slick.driver.JdbcProfile 11 12 class UserDAO @Inject()(protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile] { 13 import driver.api._ 14 15 private val Users = TableQuery[UsersTable] 16 17 def all(): Future[Seq[User]] = db.run(Users.result) 18 19 def insert(user: User): Future[Unit] = db.run(Users += user).map { _ => () } 20 21 private class UsersTable(tag: Tag) extends Table[User](tag, "user") { 22 23 def username = column[String]("username") 24 def password = column[String]("password") 25 def name = column[String]("name") 26 27 def * = (username, password, name) <> (User.tupled, User.unapply _) 28 } 29 }
ArticleDAO
, CommentDAO
も同様に定義したが、UserDAO
と殆ど同じコードなので省略。
play consoleを起動しようとする。
activator console -Dplay.evolutions.db.default.autoApply=true
と、ブラウザが開いて下記ページが表示された。
Documentation - Lightbend Activator | @lightbend
To create new Lightbend projects Instead of using the Activator command, make sure you have sbt 0.13.13 (or higher), and use the “sbt new” command, providing the name of the template. For example, “$ sbt new akka/hello-akka.g8”. You can find a list of templates here.
Activatorコマンドは廃止になるらしく、今後はsbtコマンド使ってね、とのこと。
なるほど、Playに関してぐぐってるとactivator run
やらsbt run
やら
同じようなコマンドが出てきていたけど、そういうことだったのか。
というわけで、下記コマンドでコンソールを起動する。
問題なく起動した。
sbt console -Dplay.evolutions.db.default.autoApply=true
User
モデルをnew
してレコード追加してみる。
scala> import play.api._ scala> val env = Environment(new java.io.File("."), this.getClass.getClassLoader, Mode.Dev) scala> val context = ApplicationLoader.createContext(env) scala> val loader = ApplicationLoader(context) scala> val app = loader.load(context) scala> Play.start(app) scala> import dao.UserDAO scala> import models.User scala> import scala.concurrent.Await scala> import scala.concurrent.duration.DurationInt scala> val app2dao = Application.instanceCache[UserDAO] scala> val dao = app2dao(app) scala> val user = new User("zettaittenani", "play", "zettaittenani") scala> Await.result(dao.insert(user), 1.second) scala> Await.result(dao.all, 1.second) res5: Seq[models.User] = Vector(User(zettaittenani,play_test,zettaittenani))
レコードが入ったっぽいのでPostgreSQLの方で確認してみる。
playdb=> select * from user; current_user -------------- play
…どうやらuser
というテーブル名がPostgreSQL自体のユーザのテーブル名とバッティングしていて
追加したレコードがあるかどうかわからない。
命名変更も面倒なのでArticleのレコードで試してみる。
scala> import play.api._ scala> val env = Environment(new java.io.File("."), this.getClass.getClassLoader, Mode.Dev) scala> val context = ApplicationLoader.createContext(env) scala> val loader = ApplicationLoader(context) scala> val app = loader.load(context) scala> Play.start(app) scala> import dao.ArticleDAO scala> import models.Article scala> import scala.concurrent.Await scala> import scala.concurrent.duration.DurationInt scala> val app2dao = Application.instanceCache[ArticleDAO] scala> val dao = app2dao(app) scala> val article = new Article(1, "hogehoge") scala> Await.result(dao.insert(article), 1.second) scala> Await.result(dao.all, 1.second) res2: Seq[models.Article] = Vector(Article(1,hogehoge))
playdb=> select * from article; user_id | content ---------+---------- 1 | hogehoge
よし、入ってる。
明日はview, controllerを使って画面上からレコードのCRUDをやりたい。