[翻訳] Railsの弟、Phoenix Frameworkで遊ぼう

Michał Kalbarczykさんの2015年7月28日付のブログ記事[Playing with Phoenix Framework – Rails’ younger brother](http://blog.elpassion.com/playing-with-phoenix-framework-rails-younger-brother/)の翻訳です。
**Elixir**はよく「**Erlang**の文法を**Ruby**風にしたもの」と言われますし、開発者のJosé ValimさんがRailsの開発コアメンバーであることからか開発環境も**Ruby**をお手本にしたものが多いです。
この記事は[**Phoenix Framework**](http://www.phoenixframework.org/)について**Ruby**及び**Ruby on Rails**といろいろ比較しながら書かれています。

Phoenixについての復習も兼ねて訳してみました。

------

![phoenix_blogpost.jpg](https://qiita-image-store.s3.amazonaws.com/0/46294/f89fab11-6c23-8653-619f-3c6f3d1fe245.jpeg)


[**Phoenix**](http://www.phoenixframework.org/)について聞いたことはありますか？[**Elixir**](http://elixir-lang.org/)言語で書かれた新しいWebフレームワークです。**Elixir**はそれ自体が[**Ruby**](https://www.ruby-lang.org/)にインスパイアされており[**Erlang**](http://www.erlang.org/)仮想マシン上で動作します。そう、そこにはたくさんの繋がりや相互の参照があるわけで、いわば大きな家族がいるようなものですよ。ね？

では[Phoenix](http://www.phoenixframework.org/)と[Rails](http://rubyonrails.org/)がどのぐらい密接に関連しているか見てみましょう。その作業はOS Xの上でいくらか[Homebrew](http://brew.sh/)パッケージマネージャの助けを借りてスクラッチから行うこととします。

## 環境を作る ##

ではまず両フレームワークが依存する言語のインストールから始めましょう。Rubyと同様にElixirにも既にバージョン管理ツールの選択肢がいくつかあります。例えば[**exenv**](https://github.com/mururu/exenv)や[**kiex**](http://taylor.github.io/kiex/)などが。しかしここでは話を簡単にするためそれらは使いません。

Rubyのインストール[^1]:

```bash
$ brew install ruby
```

Elixirのインストール:

```bash
$ brew install elixir
```

次に必要なのはパッケージマネージャです。Rubyが`Gems`を持っているようにElixirのパッケージマネージャは`Hex`と呼ばれています。Rubyの`Rake`に相当するのはElixirでは`Mix`です。`Hex+Mix`は合体技でRubyの`Bundler`の依存性管理機能を持ちます。

[^1]: 雑談：永らくメインの生活マシンがWindows(+cygwin)でサーバー系がLinux(Kernel 1.3.xあたりからお世話になっています)という作業環境だったのですが昨年から公私ともにMacも使うようになりました。それまで外部の勉強会に出てみるとMac持ってきてる人ばかりなんで「このノマド気取りめ(w)」とか思ってたんですがhomebrewを使ってみてその理由が分かりました。`brew install`一発でなんでも入っちゃうんだからこれは楽。

ではMixのタスクでHexパッケージマネージャをインストールしましょう:

```bash
$ mix local.hex
```

## 基礎的なお話 ##

めったにすることじゃないのでRailsフレームワークをどうやってインストールしたか思い出してみましょう:

```bash
$ gem install rails
```

Phoenixフレームワークについても特に難しくはありません:

```bash
$ mix archive install phoenix
```

これで新しいアプリケーションを作成する準備が整いました。Railsではみんな大好きなこのコマンドを実行するだけです:

```bash
$ rails new railsapp
```

このコマンドで新しいアプリケーションがディレクトリ構成とともに生成されBundlerが依存関係のあるものをダウンロードしてインストールします。

ではPhoenixではこの作業をどのように扱うのでしょうか:

```bash
$ mix phoenix.new phoenixapp
```

おお、新しいアプリケーションが生成されて依存関係ファイルがダウンロードされたじゃないですか。美しい！[^2]

[^2]: 翻訳時に原文のノリにどこまで付き合うかは常に悩みどころです(笑)

サンプルアプリケーションをテストするにはWebサーバーを起動するしなければいけません。

Railsのサーバーは:

```bash
$ rails server
```

そしてPhoenixのサーバーは:

```bash
$ mix phoenix.server
```

で起動します。[^3]

[^3]: 正確にはどちらもこの前にアプリケーションのディレクトリにchdirする必要がありますね。なお、phoenixサーバーはデフォルトではポート番号4000で起動します。

## GET /hello_phoenix

両フレームワークはともにMVCベースなので主なビルディングブロックは`モデル`、`ビュー`,`コントローラ`となります。Railsと同じく、Phoenixもこれらのジェネレータを持っています。

```bash
$ rails generate model
```

に対して

```bash
$ mix phoenix.gen.model
```

ですね。しかし、これはお手軽なやり方です。私としては違いをはっきりさせるために基本的な機能を手動で追加するやり方を比較したいわけです。

ではウェルカムメッセージを表示するサンプルページを作ってみましょう。

最初に行うのはルーティングの追加です。Railsの場合、新しいルートを生成するには`config/routes.rb`ファイルの編集を行います:

```ruby
Rails.application.routes.draw do
  get '/hello' => 'hello#index'
end
```

Phoenixでは`web/router.ex`を以下のように記述します:

```ex
defmodule Phoenixapp.Router do
  use Phoenixapp.Web, :router
  ...
  scope "/", Phoenixapp do
    pipe_through :browser # Use the default browser stack
    get "/hello", HelloController, :index
  end
end
```

次はコントローラです。

Railsアプリでは`app/controllers/hello_controller.rb`ファイルを生成します:

```ruby
class HelloController < ApplicationController
  def index
    @text = 'Hello from Controller'
  end
end
```

Phoenixでは`web/controllers/hello_controller.ex`ファイルを生成します:

```ex
defmodule Phoenixapp.HelloController do
  use Phoenixapp.Web, :controller
 
  def index(conn, _params) do
    conn |> render "index.html", text: "Hello from Controller"
  end
end
```

ビューについてはRailsでは`erb`をPhoenixでは相当品の`eex`を使います。

Railsの場合はただひとつ`app/views/hello/index.html.erb`が必要なだけです:

```xml+erb
<h1><%= @text %></h1>
```

Phoenixはビューのテンプレートだけではなくモジュールも必要になります。それは(多かれ少なかれ)Railsのビューヘルパーのようなものです。場所は`web/views/hello_view.ex`です:

```ex
defmodule Phoenixapp.HelloView do
  use Phoenixapp.Web, :view
end
```

関連するテンプレートファイルは`web/templates/hello/index.html.eex`です:

```xml+erb
<h1><%= @text %></h1>
```

ではサーバーをもう一度起動して、ブラウザで
Railsには`http://localhost:3000/hello`
Phoenixには`http://localhost:4000/hello`とタイプしてみましょう。動きますね！この感じまた味わいたいですか :laughing: 

## 灰の中から舞い上がる ##

ベンチマークや数値に興味のない人っていますかね？ということでベンチマークを。
RailsアプリはPassengerを使って`Production`環境で行いました。Phoenixは組み込みのcowboyサーバーで走っています。実行環境はMacbook Pro(2014, 2.6GHz i5, 8GB RAM)です。

Rails:

```bash
$ passenger start -e production
$ wrk -c100 -d10s http://localhost:3000/hello/
```

```text
Running 10s test @ http://localhost:3000/hello/
  2 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   143.47ms   21.31ms 295.32ms   91.25%
    Req/Sec   346.55     39.50   440.00     74.50%
  6927 requests in 10.05s, 8.96MB read
Requests/sec:    689.55
Transfer/sec:      0.89MB
```

Phoenix:[^4]

[^4]: 本文に書いてないですがproduction環境で何故かポート4001番で実行していますね。

```bash
$ MIX_ENV=prod mix compile.protocols
$ MIX_ENV=prod PORT=4001 elixir -pa _build/prod/consolidated -S mix phoenix.server
$ wrk -c100 -d10s http://localhost:4001/hello/
```

```text
Running 10s test @ http://localhost:4001/hello/
  2 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    16.73ms    3.78ms  78.27ms   91.46%
    Req/Sec     3.02k   290.98     3.58k    83.00%
  60097 requests in 10.01s, 72.67MB read
Requests/sec:   6003.29
Transfer/sec:      7.26MB
```

単純なベンチマークを中身が空に等しいコントローラに対してやった、という点には注意してください。と今、警告したからね :laughing: 

ここで重要な事を。PhoenixはElixirで走ります。ElixirはRubyではありません。Rubyにとっても似ていますが違いがあります。

他に何が？どちらのフレームワークの`コントローラ`も`params`ハッシュをURLパラメータの管理用に持っています。エラーページはそっくりです。他にもたくさんの同等な点があります。モデルについて知りたい？Railsは[**ActiveRecord**](http://api.rubyonrails.org/classes/ActiveRecord/Base.html)を持っており同様にPhoenixには[**ecto**](http://www.phoenixframework.org/docs/ecto-models)があります。どちらも様々な[^5]データベースドライバーを持っていますしデータベースとそのスキーマをマイグレーションを通じて管理する機能があります。どちらのフレームワークにもテストフレームワークがあります。

[^5]: 現時点で**ecto**はデフォルトのデータベースとしてPostgresqlに、あとMySQL(MariaDB)とSqlite3に対応しています。なのでPhoenixを動かして何かデータを記録させるためにはPostgresqlが既にインストールされて適当に設定されている必要があります。今回の例では不要ですが。

もしあなたがRailsを知っていれば、Phoenixについても既に慣れていると言ってもいいでしょう。Phoenixはまだ出来たてです。ですからあなたにもアーリーアダプターになれるワンチャンありますよ。さあ、熱々のうちに遊んでみよう！