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

Rails Webook

自社のECを開発している会社で働いています。Rails情報やサービスを成長させる方法を書いていきます

Phoenix入門1 - Hello Phoenix

phoenix elixer

f:id:nipe880324:20151011193641p:plain:w420


Phoneixとは、elixer(※1)という言語で書かれたWebフレームワークです。
最近のiOSAndroidアプリやSPI(シングルページアプリケーショん)が普及してきたため、サーバーサイドはAPIやリアルタイムストリーミングの機能を提供することが増えてきました。
Phonixは一般的なWebのMVCに加え、デフォルトでAPIやソケットによるリアルタイムストリーミング機能を提供していて、このようなニーズに対応しやすくなっています。

レイテンシーがとても低く、Phoenixのレスポンスタイムはミリセカンドの代わりにマイクロセカンドで表示されるぐらい早さが段違いと言われています。
また、Railsのコントリビュータが作っているだけありかなりRailsの仕組みに似ているので、RailsなどのMVCフレームワークに触れている方には、かなり理解しやすいと思います。
若干、elixirの独特な文法があるため、必要に応じてElixir 基礎文法最速マスターelixier - 公式を参考にしてください。




※1 earlang(アーラン)は、高可用性で大規模な並列処理が可能なリアルタイムシステムを構築するためにの関数型言語です。例えば、Facebookが買収したWhat's Appという月間アクティブユーザ8億人以上のメッセージアプリ(LINEのようなもの)でも使われています。
しかし、文法が独特で書きづらいというところ不満点があり、それを解決するために、elixerというRuby風のわかりやすいシンタックスで書きやすく、読みやすくした言語が作られました。exlixerはearlang VM上で動くバイトコードに変換されて実行されます。

この記事では、「Phonix環境のセットアップから、静的ページを作成し、表示させる」ことを行います。
次回の記事では、「Phoneixで認証機能」を実装します。
そして、最後に、WebSocketを使った次回は「チャット機能」を実装します。

サンプル

動作確認


1. Phoenix環境のセットアップ

Elixerをインストール

PhoenixはElixerで書かれています。そのため、まずElixerをインストールします。

macでHomebrewを使ってインストールする場合はbrewコマンドを使います。

$ brew update
$ brew install elixir

他のOSや方法でインストールしたい場合は、Elixerのインストールページを参照してインストールしてください。

Erlangのインストール

ElixirはErlangコンパイルされて、Erlang VM上で動きます。そのため、Erlangのインストールが必要です。
brewコマンドでElixerをインストールした場合、一緒にErlangもインストールされていれますので、インストールされていることを確認します。

$ which erl
/usr/local/bin/erl

インストールされていない場合は、Erlangのインストール方法を参照してインストールしてください。

Hex(パッケージマネージャ)のインストール

mix local.hexでHexというErlangのパッケージマネージャをインストールします。

$ mix local.hex

Phoenixのインストール

Phonixのアーカイブをローカルに取得します。

$ mix archive.install https://github.com/phoenixframework/phoenix/releases/download/v1.0.3/phoenix_new-1.0.3.ez

node.js (>=0.12.0) のインストール

PhoenixJavascriptCSSなどのアセット管理にbranch.ioというビルドツールを使っています。(他に有名なビルドツールとして、gruntやgulpというものがあります。)
そのbranch.ioがnpm(node用のパッケージマネージャ)を使っているのでnode.jsとnpmが必要になります。

nodeとnpmコマンドが使えるか確認し、使えな場合はインストールします。

$ which node
/usr/local/bin/node
$ which npm
/usr/local/bin/npm

# nodeやnpmがない場合はインストール
$ brew install node

その他のOSや方法の場合は、node.jsのインストールを参照してインストールしてください。

PostgreSQLのインストール

PhonexはデフォルトでPostgresを使う設定になっています。そのため、Postgresが必要になります。

brew install postgres

もしMySQLを使いたい場合は、プロジェクトを作成するときに--database mysqlを指定すればよいようです。

これで一通りPhonix環境がセットアップ出来ました。
簡単にまとめると、

  • Phonixは、Elixerで書かれていて、ElixerはEarlang VM上で動作するのでEarlangも必要
  • Phonixの依存ライブラリのパッケージ管理は、HexというEarlangのパッケージマネージャを使う
  • Phonixのアセット管理は、branch.ioというビルドツールを使っている。branch.ioを使うためには、node.jsやnpmが必要
  • PhonixのデフォルトのDBは、Postgresを使う。もちろん、MySQLや他のDBも使える

という形になっていて、これらのツールをインストールしました。



2. Phoenixプロジェクトの作成とサーバー起動

Phoenixプロジェクトの作成

mix phonnix.newコマンドで新規のPhoenixプロジェクトを作成します。

$ mix phoenix.new chat_phoenix
* creating chat_phoenix/config/config.exs
* creating chat_phoenix/config/dev.exs
...

Fetch and install dependencies? [Yn] Y
* running npm install && node node_modules/brunch/bin/brunch build
* running mix deps.get
...

Postgresのセットアップ

PhoenixはデフォルトでPostgresを使います。
また、ユーザ名:postgres、パスワード:postgresのアカウントが必要になります。
createuserコマンドでpostgresアカウントをパスワードpostgresで作成します。一応、DB、ロール作成権限をつけておきます。

createuser postgres --createdb --createrole --encrypted --password
Password: postgres

既にpostgresアカウントがある場合や別のアカウントを使いたい場合は、config/dev.exsの一番下にユーザ名とパスワードが記載されていますので、こちらを変更してください。

# config/dev.exs

# Configure your database
config :chat_phoenix, ChatPhoenix.Repo,
  adapter: Ecto.Adapters.Postgres,
  username: "postgres",
  password: "postgres",
  database: "chat_phoenix_dev",
  hostname: "localhost",
  pool_size: 10

データベースの作成

mix ecto.createコマンドでdev環境用のデータベースを作成します。

cd chat_phoenix
mix ecto.create
=> chat_phoenix_devデータベースが作成される

# また、MIX_ENV=testを指定することでtest環境用のデータベースが作成できます
env MIX_ENV=test mix ecto.create
=> chat_phoenix_testデータベースが作成される

ectoは、データベース操作やSQLクエリを簡単に記載できるElixerのDSLです。RubyでいうActiveRecordのようなものです。

Phoenixサーバーの起動

mix phoenix.serverでサーバーを起動します。Ctrl + cを2回おすとサーバーを停止できます。

mix phoenix.server

http://localhost:4000にアクセスすれば、次のようが画面が表示されます。
f:id:nipe880324:20151011193832p:plain:w420


開発で有用なコマンド

これで、PhoenixでWebアプリケーションを動かすことができました。
次は静的ページを追加しますが、その前に開発で使える有用なコマンドを記載します。

Phoenixの環境設定でインタラクティブにElixerコマンドを実行するにはiex -S mix phoenix.serverと実行します。iexはinteractive elixerの略です。Ctrl + cを2回押すと停止できます。

$ iex -S mix phoenix.server
iex(1)> IO.puts "こんにちは"
こんにちは
:ok

mix phoenix.routesコマンドで、Phoenixに定義されたすべてのルートを確認できます。

$ mix phoenix.routes
page_path  GET  /  ChatPhoenix.PageController :index


3. 静的ページの作成

Phonixで静的ページを追加します。それを通し、ルート、コントローラ、ビュー、テンプレートについて簡単に説明します。

Phonixのディレクトリ構成

Phonixのディレクトリ構成は次のようになっています。
主にwebにコントローラやモデル、テンプレートなどのアプリケーションのメインとなるファイルを配置します。
また、priv/staticにJSやCSS、イメージなどのアセットファイルを配置します。

chat_phoenix
├── README.md
├── _build
├── brunch-config.js
├── config
├── deps
├── lib
├── mix.exs
├── mix.lock
├── node_modules
├── package.json
├── priv
├── test
└── web

また、lib/chat_phoenix/endpoint.exがアプリケーションのエンドポイントになります。
また、lib/chat_phoenix.exがアプリケーションファイルになります。

chat_phoenix
├── lib
│   ├── chat_phoenix
│   │   ├── endpoint.ex
│   │   └── repo.ex
│   └── chat_phoenix.ex
...

ルートの追加

web/router.exにルートを記載します。
ルートの記載方法は、HTTPメソッド(GET,POSTなど)とパスをコントローラとアクションにひも付けます。
デフォルトで次のように記載されています。

# web/router.ex
defmodule ChatPhoenix.Router do
  use ChatPhoenix.Web, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  # api用のスコープ(jsonをaccept)
  pipeline :api do
    plug :accepts, ["json"]
  end

  # htmlページ用のスコープ(htmlをaccept)
  scope "/", ChatPhoenix do
    pipe_through :browser # 上記の :browser の処理を行う

    # "GET /"にアクセスすると、PageControllerのindexアクションが呼ばれる
    get "/", PageController, :index
  end

  # Other scopes may use custom stacks.
  # scope "/api", ChatPhoenix do
  #   pipe_through :api
  # end
end

ではget "/hello", HelloController, :indexという新しいルートを追加します。

scope "/", ChatPhoenix do
  pipe_through :browser # 上記の :browser の処理を行う

  get "/", PageController, :index
  # "GET /hello"にアクセスすると、HelloControllerのindexアクションが呼ばれる
  get "/hello", HelloController, :index
end

コントローラの追加

コントローラは、ルートで定義したURLからコントローラとアクションが呼ばれます。
そのため、先ほど追加したルートの、HelloControllerindexアクションを作成します。

ファイルの命名は、web/controllers/<コントローラ名>.exとなります。

# web/controllers/hello_controller.ex
defmodule ChatPhoenix.HelloController do
  # Webのcontrollerモジュールを使用できるようにする(おまじないのようなもの)
  use ChatPhoenix.Web, :controller

  # indexアクション
  #  conn - リクエスト情報を保持
  #  params - クエリストリングやフォーム入力などのパラメータ
  def index(conn, _params) do
    # index.html.eexテンプレートを表示する
    render conn, "index.html"
  end
end

※引数をメソッド内で使っていない場合は、引数名の前に_を追加することで、コンパイラでwarningが発生しなくなります。

ビューを追加

ビューは、コントローラとテンプレートの中間に位置し、プレゼンテーション層としての役割を持ちます。
コントローラから渡されたデータを表示用にフォーマットなどしてテンプレートに渡します。

ビューの命名規則は、web/views/<コントローラ名>_view.exとなります。
特にリプレゼンテーションする必要もないので空のビューを作成します。

# web/views/hello_view.ex
defmodule ChatPhoenix.HelloView do
  # Webのviewモジュールを使用できるようにする(おまじないのようなもの)
  use ChatPhoenix.Web, :view
end

テンプレートを追加

テンプレートは、HTMLやJSONを記載します。
Phoenixはデフォルトのテンプレートエンジンをeex(Embedded Elixir)を使っています。そのため、ファイルの拡張子.eexになります。

テンプレートは基本的にはweb/templates/<コントローラ名>/<アクション名>.html.eexに配置します。

<!-- web/templates/hello/index.html.eex -->
<div class="jumbotron">
  <h2>Hello Phoenix!!</h2>
</div>


静的ページの確認

http://localhost:4000/helloにアクセスすると、次のようにページが表示されます。
f:id:nipe880324:20151011193853p:plain:w420


index.html.eexのテンプレートファイルに少ししか書いてませんが、ヘッダやフッターが表示されています。
これは、web/templates/layout/app.html.eexにヘッダーやフッターが記載されているためです。
Phonixはこのapp.html.eexを表示し、このファイル内に、<%= @inner %>があり、ここにindex.html.eexテンプレートの内容が表示されています。

これで、静的ページを表示させることができました。
まとめると、

  • web/router.exでルートを追加し、HTTPメソッドとURLをコントローラーとアクションにつなげます。
  • web/controllers/<コントローラ名>.exにコントローラを作成し、アクションのメソッドを定義します。
  • web/views/<コントローラ名>_view.exでビューを作成します。
  • web/templates/<コントローラ名>/<アクション名>.html.eexにテンプレートを作成し、htmlを記載します。

という流れでした。