02 May 2014

Phoenix

Phoenixのメモを残していきます。

今日はPhoenix web framework for Elixirを参考に始めました。

セットアップ

curl https://aur.archlinux.org/packages/el/elixir/elixir.tar.gz | tar xz
cd elixir
makepkg -s --noconfirm
sudo pacman -U elixir-$pkgver-any.pkg.tar.xz --noconfirm
sudo pacman -S rebar --noconfirm

git clone https://github.com/sapporo-beam/phoenix-heroku.git # プロジェクトのクローン
cd phoenix-heroku
mix deps.get
mix phoenix.start

ドキュメントにはlocalhost:4000にアクセスする旨が記載されていますが、0.0.0.0:4000でもあるので、仮想環境にIPアドレスを割り振っている場合でもアクセスすることができます。

ルーティング

動画では、基本的なルーティングの仕方を紹介されていたのですが、途中でプログラムの内容にエラーがあるとサーバーそのものの表示がおかしくなってしまうようです。

>> Running Elixir.PhoenixHeroku.Router with Cowboy with [port: 4000, ssl: false, consider_all_requests_local: true]
GET: []
lib/phoenix_heroku/router.ex:1: warning: redefining module PhoenixHeroku.Router
== Compilation error on file lib/phoenix_heroku/router.ex ==

=ERROR REPORT==== 2-May-2014::19:39:47 ===
Error in process <0.735.0> with exit value: {[{reason,undef},{mfa,{'Elixir.Plug.Adapters.Cowboy.Handler',init,3}},{stacktrace,[{'Elixir.Exception',normalize,[{'Elixir.CompileError','__exception__',<<56 bytes>>,1,<<101 bytes>>}],[]},{'Elixir.Phoenix.Controller',error,2,[{file,"lib/phoenix/c...

実行しているコードが正しければ、再起動しなくても修正が自動で反映されるのですが、一度うまくいかなくなった場合はCtr-C aで終了してから、コードを修正して、mixコマンドを実行します。

エラー例 1

$ mix
== Compilation error on file lib/phoenix_heroku/router.ex ==
** (CompileError) lib/phoenix_heroku/router.ex:1: def page_path/1 has default values and multiple clauses, use a separate clause for declaring defaults
    (elixir) src/elixir_def.erl:286: :elixir_def.store_each/8
    (elixir) src/elixir_def.erl:101: :elixir_def.store_definition/9
    (stdlib) erl_eval.erl:657: :erl_eval.do_apply/6
    (stdlib) erl_eval.erl:121: :erl_eval.exprs/5
    /home/nzwsch/phoenix-heroku/lib/phoenix_heroku/router.ex:1: Phoenix.Router.Mapper.__before_compile__/1
# lib/phoenix_heroku/router.ex
efmodule PhoenixHeroku.Router do
  use Phoenix.Router

  plug Plug.Static, at: "/static", from: :phoenix_heroku
  get "/",      PhoenixHeroku.Controllers.Pages, :index, as: :page
  get "/pages", PhoenixHeroku.Controllers.Pages, :show,  as: :page
end

このエラーはas: :pageが重複していることに対するエラーです。

エラー例 2

$ mix
== Compilation error on file lib/phoenix_heroku/router.ex ==
** (ArgumentError) Path must start with slash.
Change path from:
pages
to
/pages

    lib/phoenix/router/errors.ex:5: Phoenix.Router.Errors.ensure_valid_path!/1
    lib/phoenix_heroku/router.ex:6: (module)
    (stdlib) erl_eval.erl:657: :erl_eval.do_apply/6
    (elixir) src/elixir.erl:150: :elixir.eval_forms/4
# lib/phoenix_heroku/router.ex
efmodule PhoenixHeroku.Router do
  use Phoenix.Router

  plug Plug.Static, at: "/static", from: :phoenix_heroku
  get "/",      PhoenixHeroku.Controllers.Pages, :index
  get "pages",  PhoenixHeroku.Controllers.Pages, :show,  as: :page
end

このエラーはどの部分を修正すべきかが表示されています。動画のコードと同じように書こうとしましたが、やはりパスの先頭は/から始めなければならないようです。

エラー例 3

$ mix
Compiled lib/phoenix_heroku/router.ex
Generated phoenix_heroku.app
# lib/phoenix_heroku/router.ex
efmodule PhoenixHeroku.Router do
  use Phoenix.Router

  plug Plug.Static, at: "/static", from: :phoenix_heroku
  get "/",      PhoenixHeroku.Controllers.Pages, :index
  get "/pages", PhoenixHeroku.Controllers.Pages, :show,  as: :page
end

変更があったファイルのみがコンパイルされ、このように表示されます。 ただし、localhost:4000/pagesへアクセスしてみると......

$ curl http://localhost:4000/pages
No route matches get to ["pages"]

このように表示されてしまいました。Phoenixではルーティングの一覧を取得する方法があるようなので調べてみます。

$ mix phoenix.routes
** (UndefinedFunctionError) undefined function: PhoenixHeroku.Config.Router.__routes__/0
    PhoenixHeroku.Config.Router.__routes__()
    lib/phoenix/router/console_formatter.ex:9: Phoenix.Router.ConsoleFormatter.format/1
    lib/mix/tasks/phoenix/routes.ex:27: Mix.Tasks.Phoenix.Routes.print_routes/1
    (mix) lib/mix/cli.ex:93: Mix.CLI.run_task/2
    (elixir) src/elixir_lexical.erl:17: :elixir_lexical.run/2
    (elixir) lib/code.ex:303: Code.require_file/2

バグなのかうまくいきませんでした。 今週はここまで。