Michał Kalbarczykさんの2015年7月28日付のブログ記事Playing with Phoenix Framework – Rails’ younger brotherの翻訳です。
Elixirはよく「Erlangの文法をRuby風にしたもの」と言われますし、開発者のJosé ValimさんがRailsの開発コアメンバーであることからか開発環境もRubyをお手本にしたものが多いです。
この記事はPhoenix FrameworkについてRuby及びRuby on Railsといろいろ比較しながら書かれています。
Phoenixについての復習も兼ねて訳してみました。
Phoenixについて聞いたことはありますか?Elixir言語で書かれた新しいWebフレームワークです。Elixirはそれ自体がRubyにインスパイアされておりErlang仮想マシン上で動作します。そう、そこにはたくさんの繋がりや相互の参照があるわけで、いわば大きな家族がいるようなものですよ。ね?
ではPhoenixとRailsがどのぐらい密接に関連しているか見てみましょう。その作業はOS Xの上でいくらかHomebrewパッケージマネージャの助けを借りてスクラッチから行うこととします。
環境を作る
ではまず両フレームワークが依存する言語のインストールから始めましょう。Rubyと同様にElixirにも既にバージョン管理ツールの選択肢がいくつかあります。例えばexenvやkiexなどが。しかしここでは話を簡単にするためそれらは使いません。
Rubyのインストール1:
$ brew install ruby
Elixirのインストール:
$ brew install elixir
次に必要なのはパッケージマネージャです。RubyがGems
を持っているようにElixirのパッケージマネージャはHex
と呼ばれています。RubyのRake
に相当するのはElixirではMix
です。Hex+Mix
は合体技でRubyのBundler
の依存性管理機能を持ちます。
ではMixのタスクでHexパッケージマネージャをインストールしましょう:
$ mix local.hex
基礎的なお話
めったにすることじゃないのでRailsフレームワークをどうやってインストールしたか思い出してみましょう:
$ gem install rails
Phoenixフレームワークについても特に難しくはありません:
$ mix archive install phoenix
これで新しいアプリケーションを作成する準備が整いました。Railsではみんな大好きなこのコマンドを実行するだけです:
$ rails new railsapp
このコマンドで新しいアプリケーションがディレクトリ構成とともに生成されBundlerが依存関係のあるものをダウンロードしてインストールします。
ではPhoenixではこの作業をどのように扱うのでしょうか:
$ mix phoenix.new phoenixapp
おお、新しいアプリケーションが生成されて依存関係ファイルがダウンロードされたじゃないですか。美しい!2
サンプルアプリケーションをテストするにはWebサーバーを起動するしなければいけません。
Railsのサーバーは:
$ rails server
そしてPhoenixのサーバーは:
$ mix phoenix.server
で起動します。3
GET /hello_phoenix
両フレームワークはともにMVCベースなので主なビルディングブロックはモデル
、ビュー
,コントローラ
となります。Railsと同じく、Phoenixもこれらのジェネレータを持っています。
$ rails generate model
に対して
$ mix phoenix.gen.model
ですね。しかし、これはお手軽なやり方です。私としては違いをはっきりさせるために基本的な機能を手動で追加するやり方を比較したいわけです。
ではウェルカムメッセージを表示するサンプルページを作ってみましょう。
最初に行うのはルーティングの追加です。Railsの場合、新しいルートを生成するにはconfig/routes.rb
ファイルの編集を行います:
Rails.application.routes.draw do
get '/hello' => 'hello#index'
end
Phoenixではweb/router.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
ファイルを生成します:
class HelloController < ApplicationController
def index
@text = 'Hello from Controller'
end
end
Phoenixではweb/controllers/hello_controller.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
が必要なだけです:
<h1><%= @text %></h1>
Phoenixはビューのテンプレートだけではなくモジュールも必要になります。それは(多かれ少なかれ)Railsのビューヘルパーのようなものです。場所はweb/views/hello_view.ex
です:
defmodule Phoenixapp.HelloView do
use Phoenixapp.Web, :view
end
関連するテンプレートファイルはweb/templates/hello/index.html.eex
です:
<h1><%= @text %></h1>
ではサーバーをもう一度起動して、ブラウザで
Railsにはhttp://localhost:3000/hello
Phoenixにはhttp://localhost:4000/hello
とタイプしてみましょう。動きますね!この感じまた味わいたいですか
灰の中から舞い上がる
ベンチマークや数値に興味のない人っていますかね?ということでベンチマークを。
RailsアプリはPassengerを使ってProduction
環境で行いました。Phoenixは組み込みのcowboyサーバーで走っています。実行環境はMacbook Pro(2014, 2.6GHz i5, 8GB RAM)です。
Rails:
$ passenger start -e production
$ wrk -c100 -d10s http://localhost:3000/hello/
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
$ 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/
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
単純なベンチマークを中身が空に等しいコントローラに対してやった、という点には注意してください。と今、警告したからね
ここで重要な事を。PhoenixはElixirで走ります。ElixirはRubyではありません。Rubyにとっても似ていますが違いがあります。
他に何が?どちらのフレームワークのコントローラ
もparams
ハッシュをURLパラメータの管理用に持っています。エラーページはそっくりです。他にもたくさんの同等な点があります。モデルについて知りたい?RailsはActiveRecordを持っており同様にPhoenixにはectoがあります。どちらも様々な5データベースドライバーを持っていますしデータベースとそのスキーマをマイグレーションを通じて管理する機能があります。どちらのフレームワークにもテストフレームワークがあります。
もしあなたがRailsを知っていれば、Phoenixについても既に慣れていると言ってもいいでしょう。Phoenixはまだ出来たてです。ですからあなたにもアーリーアダプターになれるワンチャンありますよ。さあ、熱々のうちに遊んでみよう!
-
雑談:永らくメインの生活マシンがWindows(+cygwin)でサーバー系がLinux(Kernel 1.3.xあたりからお世話になっています)という作業環境だったのですが昨年から公私ともにMacも使うようになりました。それまで外部の勉強会に出てみるとMac持ってきてる人ばかりなんで「このノマド気取りめ(w)」とか思ってたんですがhomebrewを使ってみてその理由が分かりました。
brew install
一発でなんでも入っちゃうんだからこれは楽。 ↩ -
翻訳時に原文のノリにどこまで付き合うかは常に悩みどころです(笑) ↩
-
正確にはどちらもこの前にアプリケーションのディレクトリにchdirする必要がありますね。なお、phoenixサーバーはデフォルトではポート番号4000で起動します。 ↩
-
本文に書いてないですがproduction環境で何故かポート4001番で実行していますね。 ↩
-
現時点でectoはデフォルトのデータベースとしてPostgresqlに、あとMySQL(MariaDB)とSqlite3に対応しています。なのでPhoenixを動かして何かデータを記録させるためにはPostgresqlが既にインストールされて適当に設定されている必要があります。今回の例では不要ですが。 ↩