PlayFramework事始め
PlayFramework 事始め
- PlayFramework 事始め
PlayFramework 事始め
playのインストール
公式から最新のactivatorをダウンロードしてbinディレクトリにパスを通しておく。
プロジェクトの作成
activatorからプロジェクト作成
新規プロジェクトの作成は"activator new"から行う
activator new
giter8からplayのプロジェクトを作成
giter8を使うことでsbt newでplayのプロジェクトを作成できる
sbt new playframework/play-scala-seed.g8
上記コマンドで作成したプロジェクトをInteliJに取り込んでみるとbuild.sbtでPlayのプラグインがcannot resolveになることがあります。 その場合は、以下の手順でInteliJのプロジェクトを作成します。
1.既存のtarget, .idea, .idea_modulesを削除 2.project/plugins.sbtに以下を追記 addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.6.0") 3."sbt gen-idea"を実行してプロジェクトファイルを作成。それからはInteliJで取り込んでみるとbuild.sbtで発生していたcannot resolveが消えていると思います。 それでもcannot resolveになる場合はもう一度.ideaを削除して開きなおしてみると直るかもしれないです。
コンソールの起動
cd プロジェクト名
activator
サーバを起動
[プロジェクト名] $ run
コンパイル
[プロジェクト名] $ compile
テスト
[プロジェクト名] $ test
デバッグ
ポート指定でデバッグ起動できる
activator -jvm-debug 9999
sbtの利用
Play コンソールは普通の sbt コンソールでもあるため、sbtの機能も利用することができます。 ソース更新のたびにコンパイルする
[プロジェクト名] $ ~ compile
サーバ稼働中ソース更新のたびにビルドする
[プロジェクト名] $ ~ run
ソースが更新されるたびにテストする
[プロジェクト名] $ ~ test
IDE
eclipseで開発する
project/plugins.sbtに以下のプラグインを追加する設定を行う
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "4.0.0")
それからeclipseのプロジェクトファイルを生成する
activator eclipse
InteliJ IDEA
ファイルを開くでプロジェクトとして認識してくれる
Playアプリケーションの構造
app → アプリケーションソース └ assets → コンパイルされたアセットソース └ stylesheets → 通常は LESS CSS ソース └ javascripts → 通常は CoffeeScript ソース └ controllers → アプリケーションコントローラ └ models → アプリケーションビジネス層 └ views → テンプレート build.sbt → アプリケーションビルドスクリプト conf → 設定ファイル、および (クラスパス上の) その他のコンパイルされないリソース └ application.conf → メイン設定ファイル └ routes → ルート定義 dist → プロジェクト成果物に含める任意のファイル public → 公開アセット └ stylesheets → CSS ファイル └ javascripts → Javascript ファイル └ images → 画像ファイル project → sbt 設定ファイル群 └ build.properties → sbt プロジェクトの目印 └ plugins.sbt → Play 自身の定義を含む sbt プラグイン lib → 管理されていない依存ライブラリ logs → ログフォルダ └ application.log → デフォルトログファイル target → 生成物 └ resolution-cache → 依存性に関する情報 └ scala-2.10 └ api → 生成された API ドキュメント └ classes → コンパイルされたクラスファイル └ routes → routes から生成されたソース └ twirl → テンプレートから生成されたソース └ universal → アプリケーションパッケーs時 └ web → コンパイルされた web アセット test → 単体、および機能テスト用のソースフォルダ
コントローラーを追加してみる
まず簡単なコントローラを追加してみる
package controllers import javax.inject.{Inject, Singleton} import play.api.mvc.{Action, Controller} @Singleton class TestController @Inject() extends Controller{ def index = Action { request => Ok("Got request [" + request + "]") } }
play 2.4からDIが使われるようになっている、今回はDI対象のコンポーネントがないが、DI対象のコンポーネントがある場合は@Injectアノテーションの後に引数としてDI対象コンポーネントを渡すことができる。またクラス自体に@Singletonアノテーションが付与されておりシングルトンとして扱う事を明示しているが、PlayフレームワークがDIに対応する前は普通にobject型として定義するなどしていた。
また受け取るリクエストはrequestで指定することができるが、これはplayフレームワークのplay.api.mvc.Actionクラスがリクエストを受け取る際にapplyメソッドでリクエストをパースしているようである。
それからリクエストを受け取れるようにするためのルート定義をconf/routesに追加する
GET /test controllers.TestController.index
これで"http://localhost:9000/test"にアクセスしたら自作のコントローラが呼び出されるようになる。
リクエストを暗黙のパラメータとして扱う
受け取るリクエストを暗黙のパラメータにすることもできる。受け取ったリクエストのjsonをパースするときとかは暗黙のパラメータとして受け取って
package controllers import javax.inject.{Inject, Singleton} import play.api.mvc.{Action, Controller, RequestHeader} @Singleton class TestController @Inject() extends Controller{ def index = Action { implicit request => Ok(greeting("Hello")) } private def greeting(say: String)(implicit req: RequestHeader) = say + "," + req.remoteAddress }
jsonをリクエストとして受け取れるようにする
まずはplay標準のパーサでjsonのリクエストを受け取ってみるため以下のメソッドを追加する。
def jsonReq = Action(parse.json) { request => (request.body \ "name").asOpt[String].map { name => Ok("Hello " + name) }.getOrElse { BadRequest("Missing parameter [name]") } }
それからroutesを追加
POST /json controllers.TestController.jsonReq
次に以下のコマンドでリクエストを飛ばしjsonを受け取れている事を確認する
curl ‘http://localhost:9000/json’ -H ‘Content-Type: text/json’ –data-binary ‘{“name”: “jon doh”}’
jsonをcase classにセットしてみる
次にjsonのリクエストをcase classにセットする方法を試してみたいと思う。次のようにcaseクラスとmapping、Actionメソッドを定義しておく。
case class AddTodo(categoryId:Long, title:String, text:String) implicit val addTodoForm:Form[AddTodo] = Form ( mapping( "categoryId" -> longNumber, "title"-> text, "text"-> text )(AddTodo.apply)(AddTodo.unapply) ) def jsonReq = Action { request => try{ addTodoForm.bindFromRequest.fold( errors => {BadRequest("bad request")}, validForm => { Ok("categoryId: " + validForm.categoryId + " title:" + validForm.title + " text:" + validForm.text) } ) } }
それから以下のリクエストを投げることでjsonをcase classにセットできることが確認できる
curl ‘http://localhost:9000/json’ -H ‘Content-Type: text/json’ –data-binary ‘{“categoryId”: 1, “title”: “play test”, “text”: “text”}’
Formにセットする際のバリデーション処理は以下の公式を確認する
https://www.playframework.com/documentation/ja/2.4.x/ScalaForms
jsonを返してみる
jsonをレスポンスで返すのも簡単に行える。先ほどのjsonで受け取ったリクエストをそのまま返すようにして動作確認してみたいと思う。
まず先ほど利用したコントローラに以下のメソッドを追加しておく
implicit val todoWrite = new Writes[AddTodo] { def writes(todo: AddTodo) = Json.obj( "categoryId" -> todo.categoryId, "title" -> todo.title, "text" -> todo.text ) }
それから先ほどのコントローラのメソッドのレスポンスを以下のように変更する
def jsonReq = Action { request => try{ addTodoForm.bindFromRequest.fold( errors => {BadRequest("bad request")}, validForm => { Ok(Json.toJson(validForm)) } ) } }
これで受け取ったjsonをFormにセットしてそのまま返す動作が確認できたはずである。jsonのルート要素を変更したい場合は以下のようにすれば良い
Ok(Json.obj("todo" -> validForm))
セッションを使ってみる
以下のメソッドによりセッションごとでのカウントアップを行うことができる。
def count = Action { request => val nextCount = request.session.get("count") match { case Some(x) => x.toInt + 1 case None => 1 } Ok("counta: " + nextCount).withSession( request.session + ("count" -> nextCount.toString) ) }
ただしplayフレームワークはステートレスのフレームワークとなっておりplay側ではセッションを保持せずクライアント側でクッキーとして保持させる形になっている。クライアント側で自由に帰られては困るような情報はredisなど別で持たせるような仕組みにしておく必要がある。
htmlテンプレートを使ってみる
htmlテンプレートのtwirlを使って画面を描画してみる まず以下のコントローラを作成する
package controllers import javax.inject.{Inject, Singleton} import play.api.mvc.{Action, Controller} case class User(firstName: String, lastName: String) @Singleton class SampleController @Inject() extends Controller{ def index = Action { val user = User("john", "does") Ok(views.html.sample(user)) } }
それからapp/viewsにsample.scala.htmlのファイルを作成し、以下を書き込む
@(user: User) <span>this is twirl page</span> @defining(user.firstName + " " + user.lastName) { fullName => <div>Hello @fullName</div> }
これでtwirlのページが表示されるはずである。置換周りについて詳しくか以下を参照する。
https://www.playframework.com/documentation/ja/2.4.x/ScalaTemplates
DBにアクセスする
anromを使う
play2.5では既にplayの標準ではなくなっているけどanormを使ってDBにアクセスしてみる。
依存ライブラリの追加
まずbuild.sbtのdependenciesに以下を追加する
今回は動作確認なのでDBにはh2を使う
libraryDependencies ++= Seq( jdbc, "com.typesafe.play" %% "anorm" % "2.4.0", "com.h2database" % "h2" % "1.4.193" )
DB接続先設定
それからapplication.confにDBの接続先設定として以下を記入する。defaultはplayフレームワークで扱うDB名になる
db { # You can declare as many datasources as you want. # By convention, the default datasource is named `default` # https://www.playframework.com/documentation/latest/Developing-with-the-H2-Database default.driver = org.h2.Driver default.url = "jdbc:h2:mem:play" default.username = sa default.password = "" # You can turn on SQL logging for any datasource # https://www.playframework.com/documentation/latest/Highlights25#Logging-SQL-statements default.logSql=true }
初期データの投入
h2のコンソールにアクセスする場合はactivatorのコンソールで"h2-browser"を入力する
h2-browser
h2のコンソールで接続先のDBにはapplication.confで設定した"jdbc:h2:mem:play"を指定する。
それから今回使用するDB作成のSQLを実行する
create table request_text ( id bigint identity primary key, input_text char(256) ); insert into request_text(id, input_text) values ( null, 'one text'); insert into request_text(id, input_text) values ( null, 'two text'); insert into request_text(id, input_text) values ( null, 'three text'); insert into request_text(id, input_text) values ( null, 'four text');
今回はDBのデータを永続化させていなため次回play起動時にはデータがリセットされるので注意が必要
DBオブジェクト
defaultのDBを使えるようにするために以下のクラスを作成する。使用するときはコントローラ側でDIするようにする。
package db import javax.inject.Inject import play.api.db.DBApi @javax.inject.Singleton class DefaultDB @Inject()(dbapi: DBApi){ val db = dbapi.database("default") }
DAOの作成
次にDBアクセス用のDAOを作成する
package services.repository import javax.inject.Inject import dto.RequestText import play.api.db.Database import anorm.SqlParser.get import anorm.{SQL, ~} case class RequestText(id: Long, input_text: String) @javax.inject.Singleton class TextService @Inject()() { val textParser = { get[Long]("id") ~ get[String]("input_text") map { case id ~ input_text => RequestText(id, input_text) } } def addText(requestText: String)(implicit db: Database): Option[Long] = { insertText(requestText) } def insertText(requestText: String)(implicit db: Database) = { db.withConnection { implicit connection => SQL( """ insert into request_text (id, input_text) values ( (select nextval('text_id_seq')), {request_text} ) """ ).on( 'request_text -> requestText ).executeInsert() } } def getText()(implicit db: Database): Seq[RequestText] = { db.withConnection { implicit connection => SQL("select * from request_text").as(textParser.*) } } }
コントローラ側からDAOを利用する
それから、DBとDAOをDIして利用するコントローラも作成する
package controllers import javax.inject.{Inject, Singleton} import db.DefaultDB import dto.RequestText import play.api.data.Form import play.api.data.Forms._ import play.api.data.Forms.mapping import play.api.i18n.MessagesApi import play.api.mvc.{Action, Controller} import services.repository.TextService @Singleton class SampleController @Inject()(val messagesApi: MessagesApi,defaultDB: DefaultDB,textService: TextService) extends Controller{ val db = defaultDB.db def anormSample = Action { implicit request => db.withTransaction { tr => val texts:Seq[RequestText] = textService.getText()(db) Ok(views.html.sample(texts)) } } case class AddText(input_text:String) implicit val addTextForm:Form[AddText] = Form ( mapping( "input_text"-> text )(AddText.apply)(AddText.unapply) ) def anormAdd = Action { implicit request => addTextForm.bindFromRequest.fold( errors => {BadRequest("bad request")}, validForm => { db.withTransaction{ tr => textService.insertText(validForm.input_text)(db) } } ) Redirect("/anorm") } }
DBオブジェクトとDAOはDIさせて利用している
最後に動作確認ように以下のhtmlを準備したらanormの確認が行えるはず
@import dto.RequestText @(requestTexts: Seq[RequestText]) <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>anorm sample page</title> </head> <body> <span>this is anorm sample</span> <form method="post" action="anorm"> <input type="text" name="input_text" ></input><input type="submit" name="butto" value="送信" /> </form> <ul> @for(requestText <- requestTexts) { <li>@requestText.id: @requestText.input_text</li> } </ul> </body> </html>
今回はコントローラ側から暗黙のパラメータとしてDBを渡すようにしており、利用するDBを切り替える場合にも簡単に対応できる。トランザクション処理は"db.withTransaction"で行うことができる
ScalikeJDBCを使う
次にScalikeJDBCを試してみたいと思います。 まずbuild.sbtのlibDependenciesが以下になるようにします。
libraryDependencies ++= Seq( filters, "com.h2database" % "h2" % "1.4.193", "org.scalikejdbc" %% "scalikejdbc" % "2.5.1", "org.scalikejdbc" %% "scalikejdbc-config" % "2.5.1", "org.scalikejdbc" %% "scalikejdbc-play-initializer" % "2.5.1", "org.scalatestplus.play" %% "scalatestplus-play" % "2.0.0" % Test )
それからconf/application.confに以下を追加します。
scalikejdbc.global.loggingSQLAndTime.enabled=true scalikejdbc.global.loggingSQLAndTime.singleLineMode=false scalikejdbc.global.loggingSQLAndTime.logLevel=debug scalikejdbc.global.loggingSQLAndTime.warningEnabled=true scalikejdbc.global.loggingSQLAndTime.warningThresholdMillis=5 scalikejdbc.global.loggingSQLAndTime.warningLogLevel=warn play.modules.enabled += "scalikejdbc.PlayModule" # scalikejdbc.PlayModule doesn't depend on Play's DBModule play.modules.disabled += "play.api.db.DBModule"
Query DSLでSQLを実行してみる
それではまずは一覧表示できるようにしてみたいと思います。 以下のmodelを追加します。
import scalikejdbc._ case class RequestTexts(id: Long, input_text: String) { def save()(implicit session: DBSession = RequestTexts.autoSession): RequestTexts = RequestTexts.save(this)(session) def destroy()(implicit session: DBSession = RequestTexts.autoSession): Int = RequestTexts.destroy(this)(session) } object RequestTexts extends SQLSyntaxSupport[RequestTexts] { override val autoSession = AutoSession override val schemaName = Some("PUBLIC") override val tableName = "request_text" override val columns = Seq("id", "input_text") val r = RequestTexts.syntax("r") def apply(r: SyntaxProvider[RequestTexts])(rs: WrappedResultSet): RequestTexts = apply(r.resultName)(rs) def apply(r: ResultName[RequestTexts])(rs: WrappedResultSet): RequestTexts = new RequestTexts( id = rs.get(r.id), input_text = rs.get(r.input_text) ) def save(entity: RequestTexts)(implicit session: DBSession = autoSession): RequestTexts = { withSQL { update(RequestTexts).set( column.id -> entity.id, column.input_text -> entity.input_text ).where.eq(column.id, entity.id) }.update.apply() entity } def destroy(entity: RequestTexts)(implicit session: DBSession = autoSession): Int = { withSQL { delete.from(RequestTexts).where.eq(column.id, entity.id) }.update.apply() } def findAll()(implicit session: DBSession = autoSession): List[RequestTexts] = { withSQL(select.from(RequestTexts as r)).map(RequestTexts(r.resultName)).list.apply() } }
それからmodelを利用するコントローラを追加します。
package controllers import javax.inject._ import models.RequestTexts import play.api.data.Form import play.api.data.Forms.mapping import play.api.data.Forms._ import play.api.libs.json.{JsError, Json, Writes} import play.api.mvc._ import scalikejdbc.DB @Singleton class ScalikeJdbcController @Inject() extends Controller { // jsonの書き込み implicit val requestWrite = new Writes[RequestTexts] { def writes(request: RequestTexts) = Json.obj( "id" -> request.id, "input_text" -> request.input_text ) } def list = Action { implicit request => DB.readOnly { implicit session => Ok(Json.obj("root" -> RequestTexts.findAll())) } } }
あとはapiを利用できるようにするためconf/routesに以下を追加します。
GET /scalike controllers.ScalikeJdbcController.list
これで以下のコマンドを実行するとjsonのレスポンスが確認できると思います。 curl ‘http://localhost:9000/scalike’
id指定でselectする場合は以下のようにwhereのパラメータを渡すことができる
def findById(id: Long)(implicit session: DBSession = autoSession): Option[RequestTexts] = { withSQL {select.from(RequestTexts as r).where.eq(r.id, id) }.map(RequestTexts(r.resultName)).single.apply() }
SQLInterpolationでSQLを実行してみる
実行するSQLを自分で書きたい場合は以下のようになります。
def findByIdWithQuery(id: Long)(implicit session: DBSession = autoSession): Option[RequestTexts] = { sql"select id, input_text from request_text where id = ${id}" .map{rs => RequestTexts(rs.long("id"), rs.string("input_text"))}.single.apply }
insertを実行する
insert文は以下のようになります。
def create(entity: RequestTexts)(implicit session: DBSession = autoSession): RequestTexts = { val generatedKey = withSQL { insert.into(RequestTexts).namedValues( column.input_text -> entity.input_text ) }.updateAndReturnGeneratedKey.apply() RequestTexts( id = generatedKey, input_text = entity.input_text) }
slick3を使ってみる
slick3も使ってみたいと思います。
build.sbtが以下になるようにします。
libraryDependencies ++= Seq( filters, "com.h2database" % "h2" % "1.4.193", "com.typesafe.play" %% "play-slick" % "2.0.2", "com.typesafe.slick" %% "slick-codegen" % "3.1.1", "org.scalatestplus.play" %% "scalatestplus-play" % "2.0.0" % Test )
それからapplication.confでDBの接続先を設定します。Anorm、scalikeとは設定が違うので注意です。
slick.dbs.default.driver="slick.driver.H2Driver$" slick.dbs.default.db.driver=org.h2.Driver slick.dbs.default.db.url="jdbc:h2:mem:play" slick.dbs.default.db.user=sa slick.dbs.default.db.password=""
SourceCodeGeneratorでモデルを自動生成する
SourceCodeGeneratorを使ってモデルのクラスを自動で生成したいと思います。次のobjectを作成しておいてください。
package tool.codegen import slick.codegen.SourceCodeGenerator object SlickCodgeGen { def main(args: Array[String]): Unit = { codeGen } def codeGen: Unit ={ val slickDriver = "slick.driver.H2Driver" val jdbcDriver = "org.h2.Driver" val url ="jdbc:h2:mem:play" val user = "sa" val password = "" val outputFolder = "app" val pkg = "models" SourceCodeGenerator.main( Array( slickDriver, jdbcDriver, url, outputFolder, pkg, user, password ) ) } }
あとはcodeGenを呼び出せば良いのですが、プロジェクト作成時に作られるHomeControllerの最初の部分で呼び出すようにしてみます。
package controllers import javax.inject._ import play.api._ import play.api.mvc._ @Singleton class HomeController @Inject() extends Controller { import tool.codegen.SlickCodgeGen SlickCodgeGen.codeGen def index = Action { implicit request => Ok(views.html.index()) } }
これでhttp://localhost:9000/にアクセスするとモデルクラスが自動で生成されると思います。
テーブルのカラムのデフォルト値をnextval(‘自作seq’)などとしているとモデルクラスを作成するときにエラーになりました。その場合はカラムにauto incrementを付与するなどしてDB自体の機能で自動採番させれば大丈夫なようです。PostgreSQLならserial, bigserial型を使えば良さそうだと思います。
一覧表示してみる
それからmodelを利用するコントローラを追加します。
package controllers import play.api.mvc._ import play.api.libs.concurrent.Execution.Implicits.defaultContext import play.api.db.slick._ import slick.driver.JdbcProfile import models.Tables._ import javax.inject.Inject import javax.inject.Singleton import slick.driver.H2Driver.api._ import play.api.libs.json._ @Singleton class SlickContorller @Inject()(val dbConfigProvider: DatabaseConfigProvider) extends Controller with HasDatabaseConfigProvider[JdbcProfile] { // jsonの書き込み implicit val requestWrite = new Writes[RequestTextRow] { def writes(request: RequestTextRow) = Json.obj( "id" -> request.id, "input_text" -> request.inputText ) } def list = Action.async { implicit rs => db.run(RequestText.sortBy(t => t.id).result).map{ texts => Ok(Json.obj("root" -> texts)) } } }
あとはapiを利用できるようにするためconf/routesに以下を追加します。
GET /slick controllers.SlickContorller.list
これで以下のコマンドを実行するとjsonのレスポンスが確認できると思います。 curl ‘http://localhost:9000/slick’
DatabaseForconfigで使用するDBを選択する
Slick3では使用するDBを変更することも簡単に行えます。まずapplication.confを以下のようにして新しいDB接続設定を追記してください。
mydb = { driver=org.h2.Driver url="jdbc:h2:mem:play" user=sa password="" }
それから一覧表示するコントローラを以下のように編集してください。
package controllers import play.api.mvc._ import play.api.libs.concurrent.Execution.Implicits.defaultContext import play.api.db.slick._ import slick.driver.JdbcProfile import models.Tables._ import javax.inject.Inject import javax.inject.Singleton import slick.driver.H2Driver.api._ import play.api.libs.json._ @Singleton class SlickContorller @Inject() extends Controller { val mydb = Database.forConfig("mydb") // jsonの書き込み implicit val requestWrite = new Writes[RequestTextRow] { def writes(request: RequestTextRow) = Json.obj( "id" -> request.id, "input_text" -> request.inputText ) } def list = Action.async { implicit rs => mydb.run(RequestText.sortBy(t => t.id).result).map{ texts => Ok(Json.obj("root" -> texts)) } } }
これで'http://localhost:9000/slick'にアクセスすると新しく用意した接続先が使えていることが確認できます。
ID指定で取得する
先ほどは一覧表示したので今回はidを指定してみたいと思います。コントローラに以下のidでフィルターをかけるメソッドを追加します。
def findById(id: Long) = Action.async {implicit rs => mydb.run(RequestText.filter(t => t.id === id).result).map{ text => Ok(Json.obj("root" -> text)) } }
それからroutesに以下を追加してメソッドを呼び出せるようにします。
GET /find/:id controllers.SlickContorller.findById(id :Long)
これで'curl ‘http://localhost:9000/find/2'のようにid指定でSQLを実行できるのを確認できます。
createを実行する
次にinsertを行ってみます。先ほどのコントローラーに以下を追加します。
case class Reuqest(input_text:String) // jsonの読み込み implicit val addRequestForm:Form[Reuqest] = Form ( mapping( "input_text"-> text )(Reuqest.apply)(Reuqest.unapply) ) def create = Action.async { implicit rs => addRequestForm.bindFromRequest.fold( error => { Future { BadRequest(Json.obj("result" ->"failure")) } }, form => { val requestTextRow = RequestTextRow(0, Option(form.input_text)) mydb.run(RequestText += requestTextRow).map { _ => Ok(Json.obj("result" -> "success")) } } ) }
それからroutesに以下を追加します。
POST /create controllers.SlickContorller.create
これで以下のコマンドを実行するとinsertが行えているのが確認できるはずです。
curl -H “Content-type: application/json” -XPOST -d ‘{“input_text”:“new text”}’ http://localhost:9000/create
updateを実行する
updateを実行する場合は以下のようになります。
def update (id: Long)= Action.async { implicit rs => addRequestForm.bindFromRequest.fold( error => { Future { BadRequest(Json.obj("result" ->"failure")) } }, form => { val requestTextRow = RequestTextRow(id, Option(form.input_text)) mydb.run(RequestText.filter(t => t.id === requestTextRow.id.bind).update(requestTextRow)).map { _ => Ok(Json.obj("result" -> "success")) } } ) }
それからroutesに以下を追加します。
POST /update/:id controllers.SlickContorller.update(id :Long)
これで以下のコマンドを実行するとupdateが行えているのが確認できるはずです。
curl -H “Content-type: application/json” -XPOST -d ‘{“input_text”:“update text”}’ http://localhost:9000/update/2
deleteを実行する
updateを実行する場合は以下のようになります。
def delete(id: Long) = Action.async {implicit rs => mydb.run(RequestText.filter(t => t.id === id).delete).map { _=> Ok(Json.obj("result" -> "success")) } }
それからroutesに以下を追加します。
POST /delete/:id controllers.SlickContorller.delete(id :Long)
これで以下のコマンドを実行するとdeleteが行えているのが確認できるはずです。
curl -H “Content-type: application/json” -XPOST -d ‘{}’ http://localhost:9000/delete/3