読者です 読者をやめる 読者になる 読者になる

プログラミング 美徳の不幸

Ruby, Rails, JavaScriptなどのプログラミングまとめ、解説、備忘録。

play2を触る

play2触ってみた。

◯インストール

brew install scala
brew install play

play new play2Sample; cd play2Sample

play run #=> localhost:9000で初期状態のものが起動するはず

◯ルーティング
conf/routes

GET /threads controllers.Threads.index
GET /threads/:id controllers.Threads.show(id: Long)

単なるテキストファイルなのだけど、なんとなくRailsのroutes.rbに近い書き方ができる。PUTとDELETEをサポートしてるかは知らない。

◯controller
app/controllers/Threads.scala

package controllers

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

object Threads extends Controller {
  
  val threadForm = Form(
    "title" -> nonEmptyText(maxLength = 100)
  )

  def index = Action {
    Ok(views.html.threads.show(threadForm, Thread.all()))
  }
}

ここで分かるようにcontroller側でformのオブジェクトを作ってやる必要がある。というか、基本的にviewでできるのは変数の埋め込みとif文なり繰り返し程度で(それはrailsでも一緒だけど), controllerに責務が集中する。

例えばmaxLengthとかはmodelで定義するのがrails流だけど、play2はcontrollerがコンテキストになっているからcontrollerあるいはactionごとにvalidationの内容を変更するのが可能、だけど、それって要るかな...


◯model

package models

import anorm._
import anorm.SqlParser._
import java.util.Date
import org.joda.Time._
import play.api.db._
import play.api.Play._

case class Thread(
  id: Long, title: String, createdAt: Date
)

object Thread {
  val simple = {
    get[Long]("id") ~
    get[String]("title") ~
    get[Date]("created_at") map {
      case id~title~createdAt =>
        Thread(id, title, createdAt)
    }
  }

  def all(): List[Thread] = {
    DB.withConnection { implicit c =>
      SQL(
        "select * from threads order by created_at desc"
      ).as(simple *)
    }
  }
}

という具合に、play2ではORMを使わないのが流儀のようだ。一応ORMもあるけど、フレームワークの解説ページでSQLがDSLだとなんだの言ってたので使わないほうがイケてると言わんばかりである。

これをviewに描画するとこうなる。

◯app/views/threads/index.scala.html

@(threadForm: Form[String], threads: List[Thread])

@import helper._

@main("thread form") {
  @form(routes.Threads.create()) {
    @textarea(threadForm("title"))
    <input type='submit' value='作成' />
  }
  @for(thread <- threads) {
    <li><a href="/threads/@thread.id">@thread.title</a></li>
  }
}

mainはlayout。@ではじまるのがscalaの変数なり関数であることを示している。
二重引用符の中の@は展開されて、シングルクオートは展開されない。

細かいことはサンプルをあげたからこれを見てほしい。
https://github.com/t-kot/play2Sample



■雑感
1. ORMがないことに対して
ORMがないのはあれだけど使いづらいものがデファクトスタンダードになってるよりはマシだと思う。ただ、modelに対してallとかorderとか、汎用的に使いがちなものを毎回定義しないといけないのかな。
Rubyの発想だったらそんなのモジュール化できるだろって思うのだが、scalaもたぶん大丈夫だろう。

2. scalaという言語に対して
言語自体は難解で多機能だと思う。
新人研修でちょろっと勉強させて、なんとなく書ける言語ではないのではなかろうか。