Play2 + Slickハンズオンの補足メモ

## はじめに

この記事は、ビズリーチのPlay2とSlickを使ってWebアプリケーションを作成するハンズオンを、
Scala歴ほぼ1ヶ月の私がやってみた際に、つまづいた、または調べた内容をまとめたものです。
私と同じようにScalaの勉強を進めている方の助けになれば幸いに思います。

http://bizreach.github.io/play2-hands-on/

いくつかフレームワークとバージョンの組み合わせがあるのですが、今回は、Play2.5 + Slick3.1のハンズオンをやってみました。

http://bizreach.github.io/play2-hands-on/play2.5-slick3.1/introduction.html

以下、ハンズオン各章について、つまづいた点、調べた点をまとめていきます。

## イントロダクション

- Play2とは
    - JavaとScalaのWebアプリケーションフレームワーク

- Slickとは
    - Scala Language-Integrated Connection Kit
    - RDBを簡単に扱うための、ScalaのFRM(Functional Relational Mapping)ライブラリ
    - Scalaのコレクションを扱うような操作でDBにアクセスし、データを操作可能

## プロジェクトの作成

以下の2つは同じであるようです。

**build.sbt**

```scala
libraryDependencies += "com.typesafe.play" %% "play-slick_2.11.8" % "2.0.2"
```

```scala
scalaVersion := "2.11.8"
libraryDependencies += "com.typesafe.play" %% "play-slick" % "2.0.2"
```

## IDEの準備

特になし

## DBの準備

### H2の起動

Mac, もしくはLinuxの場合、`sh start.sh`で起動するのですが、その状態を維持しなくてはならないので、次の作業を行うために別でターミナルを開く必要があります。

## ルーティングの定義

### コントローラの雛形を作る

「`controllers`パッケージに`UserController`クラスを以下のように作成します。」
というのは、
「`app/controllers`ディレクトリ配下に`UserController.scala`を作成し、そのファイルに`UserController`クラスを定義する」
ということみたいです。

- DI機能とは
    - Dependency Injection(依存性注入)
    - 依存関係解決、コンポーネントの動作を分離などに役立つ

## ユーザ一覧の実装

### ビュー

`list.scala.html`は`views/user`ディレクトリを作成し、その配下に作成します。

## ユーザ登録・編集画面の実装

特になし

## 登録・更新処理の実装

`userForm.bindFromRequest`です。
`userForm.bindFormRequest`ではありません。
私はこの打ち間違えに気がつかず、10分ほど無駄にしました。

## 削除処理の実装

特になし

## JSON APIの準備

`app/controllers`ディレクトリ配下に`JsonController.scala`を作成し、そのファイルに`JsonController`クラスを定義します。

## ユーザ一覧APIの実装

- DSLとは
    - Domain Specific Language(ドメイン特化言語)
    - ある分野に固有の語彙や語法を使用して事象を表現できるよう作られたプログラミング言語
    - 大きく内部DSLと外部DSLに分類可能
    - 内部DSL: 
        - 汎用のプログラミング言語の書き方を工夫して、見かけ上の構文を自然言語に近づけた言語
    - 外部DSL:
        - 汎用のプログラミング言語とはまったく別の構文を持ったDSL

DSLを使わない記述の場合、以下のようにコンパニオンオブジェクトを定義します。

```Scala:app/controllers/JsonController.scala
object JsonController {
  implicit val usersRowWritesFormat = new Writes[UsersRow] {
    def writes(user: UsersRow): JsValue = {
      Json.obj(
        "id" -> user.id,
        "name" -> user.name,
        "companyId" -> user.companyId
      )
    }
  }
}
```

これを`JsonController.scala`に追加し、`JsonController`の`list`メソッドを実装します。
そして、`curl -XGET http://localhost:9000/json/list`でユーザ一覧のJSONを取得するのですが、以下のエラーが出てしまいました。

```
[error] type mismatch;
[error]  found   : Seq[models.Tables.Users#TableElementType]
[error]     (which expands to)  Seq[models.Tables.UsersRow]
[error]  required: play.api.libs.json.Json.JsValueWrapper
[error]  Note: implicit value usersRowWritesFormat is not applicable here because it comes after the application point and it lacks an explicit result type
[error]       Ok(Json.obj("users" -> users))
[error]                              ^
```

また打ち間違えでもしたかと思ったのですが、確認してみても打ち間違いはありませんでした。
原因は、コンパニオンオブジェクトを記述する位置でした。`JsonController`クラスの下に記述していたのを、上に記述するようにしたところ、エラーは出なくなりました。
ググってもわからず途方に暮れていたのですが、GitHubに公開されている[ソースコード](https://github.com/bizreach/play2-hands-on/blob/master/projects/play2.5-slick3.1/play2-hands-on/app/controllers/JsonController.scala)を確認して気づくことができました。
暗黙の型変換の定義の結果型を省略した場合、定義より前で型変換を行うことができないため、コンパイルエラーになっていたようです。
詳しくは[こちら](https://qiita.com/sndr/items/673a1745a5af96dc5731)。

## ユーザ登録・更新APIの実装

特になし

## ユーザ削除APIの実装

特になし