1. techno-tanoC

    Posted

    techno-tanoC
Changes in title
+Elixirでtrotを使ってみる
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,158 @@
+> Trot is an Elixir web micro-framework based on Plug and Cowboy.
+
+TrotはPlugとCowboyで作られたマイクロWebフレームワークらしいです。
+
+rubyのsinatraと同じようなことをelixirでもしたくなったので色々探した結果、[trot](https://github.com/hexedpackets/trot)というパッケージを見つけたのでその使い方を簡単に紹介します。
+
+# 作る
+
+## 準備
+`mix new trot_sample`
+今回はTrotSampleというプロジェクトをmixで作りました。
+まずはmix.exsに依存関係を追加
+
+```mix.exs
+ def application do
+ [application: [:trot]]
+ end
+
+ defp deps do
+ [{:trot, github: "hexedpackets/trot"}]
+ end
+```
+
+## 設定と実装
+
+READMEに書いてあるようにconfig/config.exsに追記します。
+
+```config/config.exs
+use Mix.Config
+
+config :trot, :port, 4000
+config :trot, :router, TrotSample
+```
+
+今回は最低限の設定で。
+
+あとはメインとなるRouterを書いていきます。
+
+```lib/trot_sample.ex
+defmodule TrotSample do
+ use Trot.Router
+
+ get "/ping" do
+ "pong"
+ end
+
+ get "double/:number" do
+ number |> String.to_integer |> (&(&1 * 2)).() |> Integer.to_string
+ end
+
+ post "/echo" do
+ {:ok, body, conn} = read_body conn
+ body
+ end
+
+ post "/hello" do
+ conn = fetch_query_params(conn)
+ "Hello, #{conn.params["name"]}!"
+ end
+
+ get "/json" do
+ %{lang: "elixir"}
+ end
+end
+```
+
+上から順に
+
+* 単純なGET
+* URL中のパターンマッチ
+* POST
+* JSONを返却
+
+しています。
+
+リクエストのbodyは`read_body`、パラメータは`fetch_query_params`を使う必要があるのですが、READMEには全く書いてなくてものすごく悩みました。結局Plugについて調べている最中に発見しました。
+
+ところでパイプラインの途中で匿名関数を使うときに`(&(&1 * 2)).()`や`(fn x -> x * 2).()`と書かないといけないのはどうにかなりませんかね?
+
+# 叩く
+
+起動して叩いてみます
+
+```shell
+$ mix trot.server
+```
+
+```shell
+$ curl http://localhost:4000/ping
+pong
+$ curl http://localhost:4000/double/10
+20
+$ curl -d "are you ok?" http://localhost:4000/echo
+are you ok?
+$ curl -d "" http://localhost:4000/hello?name=techno
+Hello, techno!
+$ curl http://localhost:4000/json
+{"lang":"elixir"}
+```
+
+まだ試していませんがテンプレートをレンダリングすることもできるようです。
+
+# 静的コンテンツ
+`static`の使い方に若干嵌ったので・・・
+
+trotのソースでは`static`は以下のように定義されています。
+
+```trot.ex
+ @static_root Path.relative_to_cwd("priv/static")
+
+~~
+~~
+
+ defmacro static(at, from), do: static_plug(at, from)
+
+ defmacro static(at), do: static_plug(at, "/")
+
+ defp static_plug(at, from) do
+ quote do
+ path = Path.join(@static_root, unquote(from))
+ @plugs {Plug.Static, [at: unquote(at), from: path], true}
+ end
+ end
+```
+
+従って
+
+```static.ex
+def MyRouter do
+ static "/css", "assets"
+end
+```
+
+と書くと、内部で`Path.join(@static_root, "assets")`のようなコードがマクロによって生成されるので、静的コンテンツは`priv/static/assets/`以下に置く必要があります。そして、`/css/~`というパスのリクエストによってコンテンツが返されます。
+
+例えば`/static`にファイルを置いて、`/assets/~`というパスのリクエストによって静的コンテンツを返したい場合は
+
+```static.ex
+defmodule MyRouter do
+ @static_root "/"
+ sttic "/assets", "static"
+end
+```
+
+あるいは
+
+```static.ex
+defmodule MyRouter do
+ @static_root "static"
+ static "/assets"
+```
+
+と書けば良いわけですね。
+
+# 参考
+[hexedpackets/trot: An Elixir web micro-framework.](https://github.com/hexedpackets/trot)
+[[Elixir+Trot] Trot-Frameworkを使って"Hello Trot!!"するだけの簡単なお仕事・・・](http://qiita.com/darui_kara/items/1629278b4e0aad6ebdf4)
+[週刊Elixirライブラリ2015-3 - ハードリカーエンジニア](http://d.hatena.ne.jp/hayabusa333/20150705/1436055351)